ICU-8291 Merge some important fixes done after 4.4 back to maint-4-4. #7201 (r28825), #7480 (r27945), #7690 (r28106) and #7880 (r28493).

X-SVN-Rev: 29415
This commit is contained in:
Yoshito Umaoka 2011-02-08 20:17:00 +00:00
parent 0aac60e060
commit 722bf9dc91
15 changed files with 245 additions and 64 deletions

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2007-2009, International Business Machines
* Copyright (C) 2007-2011, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
@ -36,7 +36,7 @@ public final class DateNumberFormat extends NumberFormat {
private int maxIntDigits;
private int minIntDigits;
public DateNumberFormat(ULocale loc, char zeroDigitIn) {
initialize(loc,zeroDigitIn);
}
@ -152,6 +152,8 @@ public final class DateNumberFormat extends NumberFormat {
/*
* Note: This method only parse integer numbers which can be represented by long
*/
private static final long PARSE_THRESHOLD = 922337203685477579L; // (Long.MAX_VALUE / 10) - 1
public Number parse(String text, ParsePosition parsePosition) {
long num = 0;
boolean sawNumber = false;
@ -170,7 +172,7 @@ public final class DateNumberFormat extends NumberFormat {
if (digit < 0 || 9 < digit) {
digit = UCharacter.digit(ch);
}
if (0 <= digit && digit <= 9) {
if (0 <= digit && digit <= 9 && num < PARSE_THRESHOLD) {
sawNumber = true;
num = num * 10 + digit;
} else {

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2005-2010, International Business Machines Corporation and *
* Copyright (C) 2005-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -477,26 +477,30 @@ public class OlsonTimeZone extends BasicTimeZone {
// Post-32bit transition data is optional
}
transitionTimes64 = new long[transitionCount];
int idx = 0;
if (transPre32 != null) {
for (int i = 0; i < transPre32.length / 2; i++, idx++) {
transitionTimes64[idx] =
(((long)transPre32[i * 2]) & 0x00000000FFFFFFFFL) << 32
| (((long)transPre32[i * 2 + 1]) & 0x00000000FFFFFFFFL);
if (transitionCount > 0) {
transitionTimes64 = new long[transitionCount];
int idx = 0;
if (transPre32 != null) {
for (int i = 0; i < transPre32.length / 2; i++, idx++) {
transitionTimes64[idx] =
(((long)transPre32[i * 2]) & 0x00000000FFFFFFFFL) << 32
| (((long)transPre32[i * 2 + 1]) & 0x00000000FFFFFFFFL);
}
}
}
if (trans32 != null) {
for (int i = 0; i < trans32.length; i++, idx++) {
transitionTimes64[idx] = (long)trans32[i];
if (trans32 != null) {
for (int i = 0; i < trans32.length; i++, idx++) {
transitionTimes64[idx] = (long)trans32[i];
}
}
}
if (transPost32 != null) {
for (int i = 0; i < transPost32.length / 2; i++, idx++) {
transitionTimes64[idx] =
(((long)transPost32[i * 2]) & 0x00000000FFFFFFFFL) << 32
| (((long)transPost32[i * 2 + 1]) & 0x00000000FFFFFFFFL);
if (transPost32 != null) {
for (int i = 0; i < transPost32.length / 2; i++, idx++) {
transitionTimes64[idx] =
(((long)transPost32[i * 2]) & 0x00000000FFFFFFFFL) << 32
| (((long)transPost32[i * 2 + 1]) & 0x00000000FFFFFFFFL);
}
}
} else {
transitionTimes64 = null;
}
// Type offsets list must be of even size, with size >= 2
@ -508,13 +512,14 @@ public class OlsonTimeZone extends BasicTimeZone {
typeCount = typeOffsets.length / 2;
// Type map data must be of the same size as the transition count
typeMapData = null;
if (transitionCount > 0) {
r = res.get("typeMap");
typeMapData = r.getBinary(null);
if (typeMapData.length != transitionCount) {
throw new IllegalArgumentException("Invalid Format");
}
} else {
typeMapData = null;
}
// Process final rule and data, if any
@ -727,6 +732,18 @@ public class OlsonTimeZone extends BasicTimeZone {
} else {
buf.append("null");
}
buf.append(",typeMapData=");
if (typeMapData != null) {
buf.append('[');
for (int i = 0; i < typeMapData.length; ++i) {
if (i > 0) {
buf.append(',');
}
buf.append(Byte.toString(typeMapData[i]));
}
} else {
buf.append("null");
}
buf.append(",finalStartYear=" + finalStartYear);
buf.append(",finalStartMillis=" + finalStartMillis);
buf.append(",finalZone=" + finalZone);
@ -754,14 +771,14 @@ public class OlsonTimeZone extends BasicTimeZone {
* Offset from GMT in seconds for each type.
* Length is equal to typeCount
*/
private int[] typeOffsets; // alias into res; do not delete
private int[] typeOffsets;
/**
* Type description data, consisting of transitionCount uint8_t
* type indices (from 0..typeCount-1).
* Length is equal to transitionCount
*/
private byte[] typeMapData; // alias into res; do not delete
private byte[] typeMapData;
/**
* For year >= finalStartYear, the finalZone will be used.
@ -819,15 +836,19 @@ public class OlsonTimeZone extends BasicTimeZone {
Double.doubleToLongBits(finalStartMillis)+
(finalZone == null ? 0 : finalZone.hashCode()) +
super.hashCode());
for(int i=0; i<transitionTimes64.length; i++){
ret+=transitionTimes64[i]^(transitionTimes64[i]>>>8);
if (transitionTimes64 != null) {
for(int i=0; i<transitionTimes64.length; i++){
ret+=transitionTimes64[i]^(transitionTimes64[i]>>>8);
}
}
for(int i=0; i<typeOffsets.length; i++){
ret+=typeOffsets[i]^(typeOffsets[i]>>>8);
}
for(int i=0; i<typeMapData.length; i++){
ret+=typeMapData[i] & 0xFF;
}
if (typeMapData != null) {
for(int i=0; i<typeMapData.length; i++){
ret+=typeMapData[i] & 0xFF;
}
}
return ret;
}

View file

@ -7,7 +7,7 @@
package com.ibm.icu.util;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* Class to store version numbers of the form major.minor.milli.micro.
@ -238,7 +238,10 @@ public final class VersionInfo implements Comparable<VersionInfo>
VersionInfo result = MAP_.get(key);
if (result == null) {
result = new VersionInfo(version);
MAP_.put(key, result);
VersionInfo tmpvi = MAP_.putIfAbsent(key, result);
if (tmpvi != null) {
result = tmpvi;
}
}
return result;
}
@ -429,7 +432,7 @@ public final class VersionInfo implements Comparable<VersionInfo>
/**
* Map of singletons
*/
private static final HashMap<Integer, VersionInfo> MAP_ = new HashMap<Integer, VersionInfo>();
private static final ConcurrentHashMap<Integer, VersionInfo> MAP_ = new ConcurrentHashMap<Integer, VersionInfo>();
/**
* Last byte mask
*/

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2010, International Business Machines Corporation and *
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -70,7 +70,7 @@ final class BreakTransliterator extends Transliterator {
| (1<<Character.NON_SPACING_MARK)
| (1<<Character.ENCLOSING_MARK)
;
protected void handleTransliterate(Replaceable text, Position pos, boolean incremental) {
protected synchronized void handleTransliterate(Replaceable text, Position pos, boolean incremental) {
boundaryCount = 0;
int boundary = 0;
getBreakIterator(); // Lazy-create it if necessary

View file

@ -1,8 +1,8 @@
/*
*******************************************************************************
* Copyright (C) 2009, Google, International Business Machines Corporation *
* and others. All Rights Reserved. *
*******************************************************************************
********************************************************************************
* Copyright (C) 2009-2011, Google, International Business Machines Corporation *
* and others. All Rights Reserved. *
********************************************************************************
*/
package com.ibm.icu.text;
@ -58,7 +58,7 @@ class CaseFoldTransliterator extends Transliterator{
/**
* Implements {@link Transliterator#handleTransliterate}.
*/
protected void handleTransliterate(Replaceable text,
protected synchronized void handleTransliterate(Replaceable text,
Position offsets, boolean isIncremental) {
if(csp==null) {
return;

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2010, International Business Machines Corporation and *
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -65,7 +65,7 @@ class LowercaseTransliterator extends Transliterator{
/**
* Implements {@link Transliterator#handleTransliterate}.
*/
protected void handleTransliterate(Replaceable text,
protected synchronized void handleTransliterate(Replaceable text,
Position offsets, boolean isIncremental) {
if(csp==null) {
return;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 1996-2010, International Business Machines Corporation and
* Copyright (C) 1996-2011, International Business Machines Corporation and
* others. All Rights Reserved.
*/
package com.ibm.icu.text;
@ -14,9 +14,6 @@ import com.ibm.icu.lang.UCharacter;
*/
class NameUnicodeTransliterator extends Transliterator {
char openDelimiter;
char closeDelimiter;
static final String _ID = "Name-Any";
static final String OPEN_PAT = "\\N~{~";

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2009, International Business Machines Corporation and *
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -328,7 +328,7 @@ public class RuleBasedTransliterator extends Transliterator {
* @internal
* @deprecated This API is ICU internal only.
*/
protected synchronized void handleTransliterate(Replaceable text,
protected void handleTransliterate(Replaceable text,
Position index, boolean incremental) {
/* We keep start and limit fixed the entire time,
* relative to the text -- limit may move numerically if text is
@ -354,16 +354,18 @@ public class RuleBasedTransliterator extends Transliterator {
* number of characters n, unless n is so large that 16n exceeds a
* uint32_t.
*/
int loopCount = 0;
int loopLimit = (index.limit - index.start) << 4;
if (loopLimit < 0) {
loopLimit = 0x7FFFFFFF;
}
synchronized(data) {
int loopCount = 0;
int loopLimit = (index.limit - index.start) << 4;
if (loopLimit < 0) {
loopLimit = 0x7FFFFFFF;
}
while (index.start < index.limit &&
loopCount <= loopLimit &&
data.ruleSet.transliterate(text, index, incremental)) {
++loopCount;
while (index.start < index.limit &&
loopCount <= loopLimit &&
data.ruleSet.transliterate(text, index, incremental)) {
++loopCount;
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 1996-2010, International Business Machines Corporation and
* Copyright (C) 1996-2011, International Business Machines Corporation and
* others. All Rights Reserved.
*
*/
@ -63,7 +63,7 @@ class TitlecaseTransliterator extends Transliterator {
/**
* Implements {@link Transliterator#handleTransliterate}.
*/
protected void handleTransliterate(Replaceable text,
protected synchronized void handleTransliterate(Replaceable text,
Position offsets, boolean isIncremental) {
// TODO reimplement, see ustrcase.c
// using a real word break iterator

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2010, International Business Machines Corporation and *
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -61,7 +61,7 @@ class UppercaseTransliterator extends Transliterator {
/**
* Implements {@link Transliterator#handleTransliterate}.
*/
protected void handleTransliterate(Replaceable text,
protected synchronized void handleTransliterate(Replaceable text,
Position offsets, boolean isIncremental) {
if(csp==null) {
return;

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2001-2010, International Business Machines Corporation and *
* Copyright (C) 2001-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -3701,4 +3701,20 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
};
expect(DATA, new Locale("en", "", ""));
}
/*
* Test case for very long contiguous numeric patterns (ticket#7480)
*/
public void TestLongContiguousNumericPattern() {
String DATA[] = {
"yyyy-MM-dd HH:mm:ss.SSS",
"yyyyMMddHHmmssSSSSSS", "fp", "2010-04-16 12:23:34.456",
"20100416122334456000", "2010-04-16 12:23:34.456",
"yyyyyyMMddHHHHmmmmssssSSSSSS", "fp", "2010-04-16 12:23:34.456",
"0020100416001200230034456000", "2010-04-16 12:23:34.456",
};
expect(DATA, new Locale("en", "", ""));
}
}

View file

@ -1,6 +1,6 @@
/**
*******************************************************************************
* Copyright (C) 2000-2010, International Business Machines Corporation and *
* Copyright (C) 2000-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -1622,6 +1622,27 @@ public class TimeZoneTest extends TestFmwk
logln("Note: Errors could be the result of changes to zoneStrings locale data");
}
}
/*
* Test case for hashCode problem reported by ticket#7690 OlsonTimeZone.hashCode() throws NPE.
*/
public void TestHashCode() {
String[] ids = TimeZone.getAvailableIDs();
for (String id: ids) {
TimeZone tz1 = TimeZone.getTimeZone(id);
TimeZone tz2 = TimeZone.getTimeZone(id);
// hash code are same for the same time zone
if (tz1.hashCode() != tz2.hashCode()) {
errln("Fail: Two time zone instances for " + id + " have different hash values.");
}
// string representation should be also same
if (!tz1.toString().equals(tz2.toString())) {
errln("Fail: Two time zone instances for " + id + " have different toString() values.");
}
}
}
}
//eof

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2009, International Business Machines Corporation and *
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -342,4 +342,56 @@ public final class VersionInfoTest extends TestFmwk
"2.1.255.0",
"3.1.255.100"
};
/*
* Test case for multi-threading problem reported by ticket#7880
*/
public void TestMultiThread() {
final int numThreads = 20;
GetInstanceWorker[] workers = new GetInstanceWorker[numThreads];
VersionInfo[][] results = new VersionInfo[numThreads][255];
// Create workers
for (int i = 0; i < workers.length; i++) {
workers[i] = new GetInstanceWorker(i, results[i]);
}
// Start workers
for (int i = 0; i < workers.length; i++) {
workers[i].start();
}
// Wait for the completion
for (int i = 0; i < workers.length; i++) {
try {
workers[i].join();
} catch (InterruptedException e) {
errln("A problem in thread execution. " + e.getMessage());
}
}
// Check if singleton for each
for (int i = 1; i < results.length; i++) {
for (int j = 0; j < results[0].length; j++) {
if (results[0][j] != results[i][j]) {
errln("Different instance at index " + j + " Thread#" + i);
}
}
}
}
private class GetInstanceWorker extends Thread {
private VersionInfo[] results;
GetInstanceWorker(int serialNumber, VersionInfo[] results) {
super("GetInstnaceWorker#" + serialNumber);
this.results = results;
}
public void run() {
for (int i = 0; i < results.length; i++) {
results[i] = VersionInfo.getInstance(i);
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2009, International Business Machines Corporation and *
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -28,6 +28,7 @@ public class TestAll extends TestGroup {
"TransliteratorTest",
"RegexUtilitiesTest",
"UnicodeMapTest",
"ThreadTest"
});
}

View file

@ -0,0 +1,66 @@
/*
*******************************************************************************
* Copyright (C) 2010-2011, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.test.translit;
import java.util.ArrayList;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.Transliterator;
// Test for ICU Ticket #7201. With threading bugs in RuleBasedTransliterator, this
// test would reliably crash.
public class ThreadTest extends TransliteratorTest {
public static void main(String[] args) throws Exception {
new ThreadTest().run(args);
}
private ArrayList<Worker> threads = new ArrayList<Worker>();
private int iterationCount = 100000;
public void TestThreads() {
if (getInclusion() >= 9) {
// Exhaustive test. Run longer.
iterationCount = 1000000;
}
for (int i = 0; i < 8; i++) {
Worker thread = new Worker();
threads.add(thread);
thread.start();
}
long expectedCount = 0;
for (Worker thread: threads) {
try {
thread.join();
if (expectedCount == 0) {
expectedCount = thread.count;
} else {
if (expectedCount != thread.count) {
errln("Threads gave differing results.");
}
}
} catch (InterruptedException e) {
errln(e.toString());
}
}
}
private static final String [] WORDS = {"edgar", "allen", "poe"};
private class Worker extends Thread {
public long count = 0;
public void run() {
Transliterator tx = Transliterator.getInstance("Latin-Thai");
for (int loop = 0; loop < iterationCount; loop++) {
for (String s : WORDS) {
count += tx.transliterate(s).length();
}
}
}
}
}