ICU-8638 merge #8583 #8645 #8675 #8621 #8622 #8666 for milestone:4.8.1

X-SVN-Rev: 30349
This commit is contained in:
Steven R. Loomis 2011-07-14 19:10:50 +00:00
parent 3864491298
commit 8b95851806
12 changed files with 225 additions and 44 deletions

View file

@ -3,7 +3,7 @@
<html lang="en-US" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
<head>
<title>ReadMe for ICU 4.8</title>
<title>ReadMe for ICU 4.8.1</title>
<meta name="COPYRIGHT" content=
"Copyright (c) 1997-2011 IBM Corporation and others. All Rights Reserved." />
<meta name="KEYWORDS" content=
@ -16,9 +16,9 @@
<body class="draft">
<h1>International Components for Unicode<br />
<abbr title="International Components for Unicode">ICU</abbr> 4.8 ReadMe</h1>
<abbr title="International Components for Unicode">ICU</abbr> 4.8.1 ReadMe</h1>
<p>Last updated: 2011-May-23<br />
<p>Last updated: 2011-June-24<br />
Copyright &copy; 1997-2011 International Business Machines Corporation and
others. All Rights Reserved.</p>
<!-- Remember that there is a copyright at the end too -->
@ -1030,6 +1030,13 @@
ICU, you should use the <code>--with-iostream=old</code> configure option
when using runConfigureICU. This will prevent applications that use the
icuio library from crashing.</li>
<li>Also note that on current versions of z/OS, the <a href='http://www-01.ibm.com/support/docview.wss?uid=swg21202407&wv=1'>XPLINK version (C128) of the
C++ standard library is standard.</a> Therefore you may see an error when running
with XPLINK disabled. To avoid this error, set the following environment variable or similar:
<pre><a href='http://www-01.ibm.com/support/docview.wss?uid=swg21376279'>export _CXX_PSYSIX="CEE.SCEELIB(C128N)":"CBC.SCLBSID(IOSTREAM,COMPLEX)"</a></pre>
</li>
<li>The rest of the instructions for building and testing ICU on z/OS with
UNIX System Services are the same as the <a href="#HowToBuildUNIX">How To

View file

@ -2521,6 +2521,16 @@ int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
if (U_SUCCESS(ec) && ppos.getIndex() != pos) {
if (currency) {
u_strcpy(currency, curr);
} else {
// The formatter is currency-style but the client has not requested
// the value of the parsed currency. In this case, if that value does
// not match the formatter's current value, then the parse fails.
UChar effectiveCurr[4];
getEffectiveCurrency(effectiveCurr, ec);
if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) {
pos = -1;
continue;
}
}
pos = ppos.getIndex();
} else if (!isLenient()){

View file

@ -1962,6 +1962,7 @@ void RegexCompile::insertOp(int32_t where) {
opType == URX_CTR_LOOP ||
opType == URX_CTR_LOOP_NG ||
opType == URX_JMP_SAV ||
opType == URX_JMP_SAV_X ||
opType == URX_RELOC_OPRND) && opValue > where) {
// Target location for this opcode is after the insertion point and
// needs to be incremented to adjust for the insertion.

View file

@ -963,7 +963,7 @@ TimeZoneGenericNames::findLocal(const UnicodeString& text, int32_t start, uint32
int32_t maxLen = 0;
UVector *results = handler.getMatches(maxLen);
if ((results != NULL && (maxLen == (text.length() - start))) || fGNamesTrieFullyLoaded) {
if (results != NULL && ((maxLen == (text.length() - start)) || fGNamesTrieFullyLoaded)) {
// perfect match
gmatchInfo = new TimeZoneGenericNameMatchInfo(results);
if (gmatchInfo == NULL) {

View file

@ -1351,7 +1351,7 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types
int32_t maxLen = 0;
UVector *results = handler.getMatches(maxLen);
if ((results != NULL && (maxLen == (text.length() - start))) || fNamesTrieFullyLoaded) {
if (results != NULL && ((maxLen == (text.length() - start)) || fNamesTrieFullyLoaded)) {
// perfect match
matchInfo = new TimeZoneNameMatchInfoImpl(results);
if (matchInfo == NULL) {

View file

@ -242,10 +242,11 @@ idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCod
// don't use ICUService since we don't need fallback
#if !UCONFIG_NO_SERVICE
U_CDECL_BEGIN
static UBool U_CALLCONV currency_cleanup(void);
U_CDECL_END
#if !UCONFIG_NO_SERVICE
struct CReg;
static UMTX gCRegLock = 0;
@ -337,30 +338,6 @@ struct CReg : public U_NAMESPACE_QUALIFIER UMemory {
}
};
/**
* Release all static memory held by currency.
*/
/*The declaration here is needed so currency_cleanup(void)
* can call this function.
*/
static UBool U_CALLCONV
currency_cache_cleanup(void);
U_CDECL_BEGIN
static UBool U_CALLCONV currency_cleanup(void) {
#if !UCONFIG_NO_SERVICE
CReg::cleanup();
#endif
/*
* There might be some cached currency data or isoCodes data.
*/
currency_cache_cleanup();
isoCodes_cleanup();
return TRUE;
}
U_CDECL_END
// -------------------------------------
U_CAPI UCurrRegistryKey U_EXPORT2
@ -388,6 +365,32 @@ ucurr_unregister(UCurrRegistryKey key, UErrorCode* status)
// -------------------------------------
/**
* Release all static memory held by currency.
*/
/*The declaration here is needed so currency_cleanup(void)
* can call this function.
*/
static UBool U_CALLCONV
currency_cache_cleanup(void);
U_CDECL_BEGIN
static UBool U_CALLCONV currency_cleanup(void) {
#if !UCONFIG_NO_SERVICE
CReg::cleanup();
#endif
/*
* There might be some cached currency data or isoCodes data.
*/
currency_cache_cleanup();
isoCodes_cleanup();
return TRUE;
}
U_CDECL_END
// -------------------------------------
U_CAPI int32_t U_EXPORT2
ucurr_forLocale(const char* locale,
UChar* buff,

View file

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 1997-2010, International Business Machines
* Copyright (C) 1997-2011, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@ -32,7 +32,7 @@
#include "unicode/uobject.h"
#include "unicode/locid.h"
#include "unum.h"
#include "unicode/unum.h"
/**
* \file

View file

@ -39,6 +39,7 @@ void addNumForTest(TestNode** root);
static void TestTextAttributeCrash(void);
static void TestNBSPInPattern(void);
static void TestInt64Parse(void);
static void TestParseCurrency(void);
#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
@ -57,6 +58,7 @@ void addNumForTest(TestNode** root)
TESTCASE(TestNBSPInPattern);
TESTCASE(TestInt64Parse);
TESTCASE(TestParseZero);
TESTCASE(TestParseCurrency);
}
/** copy src to dst with unicode-escapes for values < 0x20 and > 0x7e, null terminate if possible */
@ -990,6 +992,136 @@ static void TestParseZero(void)
unum_close(unum);
}
static const UChar dollars2Sym[] = { 0x24,0x32,0x2E,0x30,0x30,0 }; /* $2.00 */
static const UChar dollars4Sym[] = { 0x24,0x34,0 }; /* $4 */
static const UChar dollars9Sym[] = { 0x39,0xA0,0x24,0 }; /* 9 $ */
static const UChar pounds3Sym[] = { 0xA3,0x33,0x2E,0x30,0x30,0 }; /* [POUND]3.00 */
static const UChar pounds5Sym[] = { 0xA3,0x35,0 }; /* [POUND]5 */
static const UChar pounds7Sym[] = { 0x37,0xA0,0xA3,0 }; /* 7 [POUND] */
static const UChar euros4Sym[] = { 0x34,0x2C,0x30,0x30,0xA0,0x20AC,0 }; /* 4,00 [EURO] */
static const UChar euros6Sym[] = { 0x36,0xA0,0x20AC,0 }; /* 6 [EURO] */
static const UChar euros8Sym[] = { 0x20AC,0x38,0 }; /* [EURO]8 */
static const UChar dollars4PluEn[] = { 0x34,0x20,0x55,0x53,0x20,0x64,0x6F,0x6C,0x6C,0x61,0x72,0x73,0 }; /* 4 US dollars*/
static const UChar pounds5PluEn[] = { 0x35,0x20,0x42,0x72,0x69,0x74,0x69,0x73,0x68,0x20,0x70,0x6F,0x75,0x6E,0x64,0x73,0x20,0x73,0x74,0x65,0x72,0x6C,0x69,0x6E,0x67,0 }; /* 5 British pounds sterling */
static const UChar euros8PluEn[] = { 0x38,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 8 euros*/
static const UChar euros6PluFr[] = { 0x36,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 6 euros*/
typedef struct {
const char * locale;
const char * descrip;
const UChar * currStr;
const UChar * plurStr;
UErrorCode parsDoubExpectErr;
int32_t parsDoubExpectPos;
double parsDoubExpectVal;
UErrorCode parsCurrExpectErr;
int32_t parsCurrExpectPos;
double parsCurrExpectVal;
const char * parsCurrExpectCurr;
} ParseCurrencyItem;
static const ParseCurrencyItem parseCurrencyItems[] = {
{ "en_US", "dollars2", dollars2Sym, NULL, U_ZERO_ERROR, 5, 2.0, U_ZERO_ERROR, 5, 2.0, "USD" },
{ "en_US", "dollars4", dollars4Sym, dollars4PluEn, U_ZERO_ERROR, 2, 4.0, U_ZERO_ERROR, 2, 4.0, "USD" },
{ "en_US", "dollars9", dollars9Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
{ "en_US", "pounds3", pounds3Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 5, 3.0, "GBP" },
{ "en_US", "pounds5", pounds5Sym, pounds5PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 5.0, "GBP" },
{ "en_US", "pounds7", pounds7Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
{ "en_US", "euros8", euros8Sym, euros8PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 8.0, "EUR" },
{ "en_GB", "pounds3", pounds3Sym, NULL, U_ZERO_ERROR, 5, 3.0, U_ZERO_ERROR, 5, 3.0, "GBP" },
{ "en_GB", "pounds5", pounds5Sym, pounds5PluEn, U_ZERO_ERROR, 2, 5.0, U_ZERO_ERROR, 2, 5.0, "GBP" },
{ "en_GB", "pounds7", pounds7Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
{ "en_GB", "euros4", euros4Sym, NULL, U_PARSE_ERROR, 4, 0.0, U_PARSE_ERROR, 4, 0.0, "" },
{ "en_GB", "euros6", euros6Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
{ "en_GB", "euros8", euros8Sym, euros8PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 8.0, "EUR" },
{ "en_GB", "dollars4", dollars4Sym, dollars4PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 4.0, "USD" },
{ "fr_FR", "euros4", euros4Sym, NULL, U_ZERO_ERROR, 6, 4.0, U_ZERO_ERROR, 6, 4.0, "EUR" },
{ "fr_FR", "euros6", euros6Sym, euros6PluFr, U_ZERO_ERROR, 3, 6.0, U_ZERO_ERROR, 3, 6.0, "EUR" },
{ "fr_FR", "euros8", euros8Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, "" },
{ "fr_FR", "dollars2", dollars2Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, "" },
{ "fr_FR", "dollars4", dollars4Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, "" },
{ NULL, NULL, NULL, NULL, 0, 0, 0.0, 0, 0, 0.0, NULL }
};
static void TestParseCurrency()
{
const ParseCurrencyItem * itemPtr;
for (itemPtr = parseCurrencyItems; itemPtr->locale != NULL; ++itemPtr) {
UNumberFormat* unum;
UErrorCode status;
double parseVal;
int32_t parsePos;
UChar parseCurr[4];
char parseCurrB[4];
status = U_ZERO_ERROR;
unum = unum_open(UNUM_CURRENCY, NULL, 0, itemPtr->locale, NULL, &status);
if (U_SUCCESS(status)) {
status = U_ZERO_ERROR;
parsePos = 0;
parseVal = unum_parseDouble(unum, itemPtr->currStr, -1, &parsePos, &status);
if (status != itemPtr->parsDoubExpectErr || parsePos != itemPtr->parsDoubExpectPos || parseVal != itemPtr->parsDoubExpectVal) {
log_err("UNUM_CURRENCY parseDouble %s/%s, expect %s pos %d val %.1f, get %s pos %d val %.1f\n",
itemPtr->locale, itemPtr->descrip,
u_errorName(itemPtr->parsDoubExpectErr), itemPtr->parsDoubExpectPos, itemPtr->parsDoubExpectVal,
u_errorName(status), parsePos, parseVal );
}
status = U_ZERO_ERROR;
parsePos = 0;
parseCurr[0] = 0;
parseVal = unum_parseDoubleCurrency(unum, itemPtr->currStr, -1, &parsePos, parseCurr, &status);
u_austrncpy(parseCurrB, parseCurr, 4);
if (status != itemPtr->parsCurrExpectErr || parsePos != itemPtr->parsCurrExpectPos || parseVal != itemPtr->parsCurrExpectVal ||
strncmp(parseCurrB, itemPtr->parsCurrExpectCurr, 4) != 0) {
log_err("UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s pos %d val %.1f cur %s, get %s pos %d val %.1f cur %s\n",
itemPtr->locale, itemPtr->descrip,
u_errorName(itemPtr->parsCurrExpectErr), itemPtr->parsCurrExpectPos, itemPtr->parsCurrExpectVal, itemPtr->parsCurrExpectCurr,
u_errorName(status), parsePos, parseVal, parseCurrB );
}
unum_close(unum);
} else {
log_data_err("unexpected error in unum_open UNUM_CURRENCY for locale %s: '%s'\n", itemPtr->locale, u_errorName(status));
}
#if 0
/* Hmm, for UNUM_CURRENCY_PLURAL, currently unum_open always sets U_UNSUPPORTED_ERROR, save this test until it is supported */
if (itemPtr->plurStr != NULL) {
status = U_ZERO_ERROR;
unum = unum_open(UNUM_CURRENCY_PLURAL, NULL, 0, itemPtr->locale, NULL, &status);
if (U_SUCCESS(status)) {
status = U_ZERO_ERROR;
parsePos = 0;
parseVal = unum_parseDouble(unum, itemPtr->plurStr, -1, &parsePos, &status);
if (status != itemPtr->parsDoubExpectErr || parseVal != itemPtr->parsDoubExpectVal) {
log_err("UNUM_CURRENCY parseDouble %s/%s, expect %s val %.1f, get %s val %.1f\n",
itemPtr->locale, itemPtr->descrip,
u_errorName(itemPtr->parsDoubExpectErr), itemPtr->parsDoubExpectVal,
u_errorName(status), parseVal );
}
status = U_ZERO_ERROR;
parsePos = 0;
parseCurr[0] = 0;
parseVal = unum_parseDoubleCurrency(unum, itemPtr->plurStr, -1, &parsePos, parseCurr, &status);
u_austrncpy(parseCurrB, parseCurr, 4);
if (status != itemPtr->parsCurrExpectErr || parseVal != itemPtr->parsCurrExpectVal ||
strncmp(parseCurrB, itemPtr->parsCurrExpectCurr, 4) != 0) {
log_err("UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s val %.1f cur %s, get %s val %.1f cur %s\n",
itemPtr->locale, itemPtr->descrip,
u_errorName(itemPtr->parsCurrExpectErr), itemPtr->parsCurrExpectVal, itemPtr->parsCurrExpectCurr,
u_errorName(status), parseVal, parseCurrB );
}
unum_close(unum);
} else {
log_data_err("unexpected error in unum_open UNUM_CURRENCY_PLURAL for locale %s: '%s'\n", itemPtr->locale, u_errorName(status));
}
}
#endif
}
}
typedef struct {
const char * testname;
const char * locale;

View file

@ -82,9 +82,10 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
TESTCASE(42,TestISOEra);
TESTCASE(43,TestFormalChineseDate);
TESTCASE(44,TestNumberAsStringParsing);
TESTCASE(45,TestStandAloneGMTParse);
/*
TESTCASE(45,TestRelativeError);
TESTCASE(46,TestRelativeOther);
TESTCASE(46,TestRelativeError);
TESTCASE(47,TestRelativeOther);
*/
default: name = ""; break;
}
@ -3568,8 +3569,27 @@ void DateFormatTest::TestFormalChineseDate() {
dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
delete usf;
}
delete sdf;
}
delete sdf;
}
// Test case for #8675
// Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
void DateFormatTest::TestStandAloneGMTParse() {
UErrorCode status = U_ZERO_ERROR;
SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status);
failure(status, "new SimpleDateFormat");
UnicodeString inText("GMT$$$");
for (int32_t i = 0; i < 10; i++) {
ParsePosition pos(0);
sdf->parse(inText, pos);
if (pos.getIndex() != 3) {
errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
}
}
delete sdf;
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -171,6 +171,8 @@ public: // package
void TestFormalChineseDate(void);
void TestStandAloneGMTParse(void);
public:
/**
* Test host-specific formatting.

View file

@ -5964,10 +5964,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
UnicodeString formatted = ctou(DATA[i]);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
Formattable parseResult;
if (numFmt != NULL && U_SUCCESS(status)) {
numFmt->parse(formatted, parseResult, status);
if (U_FAILURE(status) ||
Formattable parseResult;
ParsePosition parsePos;
numFmt->parseCurrency(formatted, parseResult, parsePos);
if (parsePos.getIndex() == 0 ||
(parseResult.getType() == Formattable::kDouble &&
parseResult.getDouble() != 1.0)) {
errln("wrong parsing, " + formatted);
@ -5985,10 +5986,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
UnicodeString formatted = ctou(WRONG_DATA[i]);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
Formattable parseResult;
if (numFmt != NULL && U_SUCCESS(status)) {
numFmt->parse(formatted, parseResult, status);
if (!U_FAILURE(status) ||
Formattable parseResult;
ParsePosition parsePos;
numFmt->parseCurrency(formatted, parseResult, parsePos);
if (parsePos.getIndex() > 0 ||
(parseResult.getType() == Formattable::kDouble &&
parseResult.getDouble() == 1.0)) {
errln("parsed but should not be: " + formatted);

View file

@ -1,4 +1,4 @@
# Copyright (c) 2001-2010 International Business Machines
# Copyright (c) 2001-2011 International Business Machines
# Corporation and others. All Rights Reserved.
#
# file:
@ -1024,11 +1024,15 @@
"(?!0{5})(\d{5})(?!-?0{4})(-?\d{4})?" "<0><1>94040</1><2>-3344</2></0>"
"(?!0{5})(\d{5})(?!-?0{4})(-?\d{4})?" "94040-0000"
"(?!0{5})(\d{5})(?!-?0{4})(-?\d{4})?" "00000-3344"
#
# Bug 8666. Assertion failure on match, bad operand to JMP_SAV_X opcode.
#
"((.??)+|A)*" "<0><1><2></2></1></0>AAAAABBBBBCCCCCDDDDEEEEE"
# Random debugging, Temporary
#
#"^(?:a?b?)*$" "a--"
"^(?:a?b?)*$" "a--"
"This is a string with (?:one |two |three )endings" "<0>This is a string with two endings</0>"
"((?:a|b|c)whoop-dee-do) | [jkl]|zed" "x"