ICU-10944 Add ByteBuffer support for Normalizer2Impl.

R=markus.icu@gmail.com

Review URL: https://codereview.appspot.com/106530045

X-SVN-Rev: 36034
This commit is contained in:
Fredrik Roubert 2014-07-15 20:32:17 +00:00
parent 08b5fb11b0
commit f58b3f8fd7
3 changed files with 61 additions and 45 deletions

View file

@ -1,13 +1,14 @@
/*
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import com.ibm.icu.text.Normalizer;
import com.ibm.icu.text.Normalizer2;
@ -318,8 +319,8 @@ public final class Norm2AllModes {
default: return null;
}
}
public static Norm2AllModes getInstance(InputStream data, String name) {
if(data==null) {
public static Norm2AllModes getInstance(ByteBuffer bytes, String name) {
if(bytes==null) {
Norm2AllModesSingleton singleton;
if(name.equals("nfc")) {
singleton=NFCSingleton.INSTANCE;
@ -337,16 +338,16 @@ public final class Norm2AllModes {
return singleton.allModes;
}
}
return cache.getInstance(name, data);
return cache.getInstance(name, bytes);
}
private static CacheBase<String, Norm2AllModes, InputStream> cache =
new SoftCache<String, Norm2AllModes, InputStream>() {
protected Norm2AllModes createInstance(String key, InputStream data) {
private static CacheBase<String, Norm2AllModes, ByteBuffer> cache =
new SoftCache<String, Norm2AllModes, ByteBuffer>() {
protected Norm2AllModes createInstance(String key, ByteBuffer bytes) {
Normalizer2Impl impl;
if(data==null) {
if(bytes==null) {
impl=new Normalizer2Impl().load(ICUResourceBundle.ICU_BUNDLE+"/"+key+".nrm");
} else {
impl=new Normalizer2Impl().load(data);
impl=new Normalizer2Impl().load(bytes);
}
return new Norm2AllModes(impl);
}

View file

@ -1,15 +1,14 @@
/*
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
@ -417,42 +416,40 @@ public final class Normalizer2Impl {
}
}
private static final IsAcceptable IS_ACCEPTABLE = new IsAcceptable();
private static final byte DATA_FORMAT[] = { 0x4e, 0x72, 0x6d, 0x32 }; // "Nrm2"
private static final int DATA_FORMAT = 0x4e726d32; // "Nrm2"
public Normalizer2Impl load(InputStream data) {
public Normalizer2Impl load(ByteBuffer bytes) {
try {
BufferedInputStream bis=new BufferedInputStream(data);
dataVersion=ICUBinary.readHeaderAndDataVersion(bis, DATA_FORMAT, IS_ACCEPTABLE);
DataInputStream ds=new DataInputStream(bis);
int indexesLength=ds.readInt()/4; // inIndexes[IX_NORM_TRIE_OFFSET]/4
dataVersion=ICUBinary.readHeaderAndDataVersion(bytes, DATA_FORMAT, IS_ACCEPTABLE);
int indexesLength=bytes.getInt()/4; // inIndexes[IX_NORM_TRIE_OFFSET]/4
if(indexesLength<=IX_MIN_MAYBE_YES) {
throw new ICUUncheckedIOException("Normalizer2 data: not enough indexes");
}
int[] inIndexes=new int[indexesLength];
inIndexes[0]=indexesLength*4;
for(int i=1; i<indexesLength; ++i) {
inIndexes[i]=ds.readInt();
inIndexes[i]=bytes.getInt();
}
minDecompNoCP=inIndexes[IX_MIN_DECOMP_NO_CP];
minCompNoMaybeCP=inIndexes[IX_MIN_COMP_NO_MAYBE_CP];
minYesNo=inIndexes[IX_MIN_YES_NO];
minYesNoMappingsOnly=inIndexes[IX_MIN_YES_NO_MAPPINGS_ONLY];
minNoNo=inIndexes[IX_MIN_NO_NO];
limitNoNo=inIndexes[IX_LIMIT_NO_NO];
minMaybeYes=inIndexes[IX_MIN_MAYBE_YES];
// Read the normTrie.
int offset=inIndexes[IX_NORM_TRIE_OFFSET];
int nextOffset=inIndexes[IX_EXTRA_DATA_OFFSET];
normTrie=Trie2_16.createFromSerialized(ds);
normTrie=Trie2_16.createFromSerialized(bytes);
int trieLength=normTrie.getSerializedLength();
if(trieLength>(nextOffset-offset)) {
throw new ICUUncheckedIOException("Normalizer2 data: not enough bytes for normTrie");
}
ds.skipBytes((nextOffset-offset)-trieLength); // skip padding after trie bytes
ICUBinary.skipBytes(bytes, (nextOffset-offset)-trieLength); // skip padding after trie bytes
// Read the composition and mapping data.
offset=nextOffset;
nextOffset=inIndexes[IX_SMALL_FCD_OFFSET];
@ -461,7 +458,7 @@ public final class Normalizer2Impl {
if(numChars!=0) {
chars=new char[numChars];
for(int i=0; i<numChars; ++i) {
chars[i]=ds.readChar();
chars[i]=bytes.getChar();
}
maybeYesCompositions=new String(chars);
extraData=maybeYesCompositions.substring(MIN_NORMAL_MAYBE_YES-minMaybeYes);
@ -471,7 +468,7 @@ public final class Normalizer2Impl {
offset=nextOffset;
smallFCD=new byte[0x100];
for(int i=0; i<0x100; ++i) {
smallFCD[i]=ds.readByte();
smallFCD[i]=bytes.get();
}
// Build tccc180[].
@ -491,14 +488,17 @@ public final class Normalizer2Impl {
}
}
data.close();
return this;
} catch(IOException e) {
throw new ICUUncheckedIOException(e);
}
}
public Normalizer2Impl load(String name) {
return load(ICUData.getRequiredStream(name));
try {
return load(ICUBinary.getByteBufferFromInputStream(ICUData.getRequiredStream(name)));
} catch(IOException e) {
throw new ICUUncheckedIOException(e);
}
}
private void enumLcccRange(int start, int end, int norm16, UnicodeSet set) {

View file

@ -1,14 +1,19 @@
/*
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.text;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.ibm.icu.impl.ICUBinary;
import com.ibm.icu.impl.Norm2AllModes;
import com.ibm.icu.util.ICUUncheckedIOException;
/**
* Unicode normalization functionality for standard Unicode normalization or
@ -175,6 +180,7 @@ public abstract class Normalizer2 {
* name as the key.
* If you know or expect the data to be cached already, you can use data!=null
* for non-ICU data as well.
* <p>Any {@link java.io.IOException} is wrapped into a {@link com.ibm.icu.util.ICUUncheckedIOException}.
* @param data the binary, big-endian normalization (.nrm file) data, or null for ICU data
* @param name "nfc" or "nfkc" or "nfkc_cf" or name of custom data file
* @param mode normalization mode (compose or decompose etc.)
@ -182,7 +188,16 @@ public abstract class Normalizer2 {
* @stable ICU 4.4
*/
public static Normalizer2 getInstance(InputStream data, String name, Mode mode) {
Norm2AllModes all2Modes=Norm2AllModes.getInstance(data, name);
// TODO: If callers really use this API, then we should add an overload that takes a ByteBuffer.
ByteBuffer bytes = null;
if (data != null) {
try {
bytes = ICUBinary.getByteBufferFromInputStream(data);
} catch (IOException e) {
throw new ICUUncheckedIOException(e);
}
}
Norm2AllModes all2Modes=Norm2AllModes.getInstance(bytes, name);
switch(mode) {
case COMPOSE: return all2Modes.comp;
case DECOMPOSE: return all2Modes.decomp;