Index: modules/nio_char/src/main/java/java/nio/charset/Charset.java =================================================================== --- modules/nio_char/src/main/java/java/nio/charset/Charset.java (revision 576863) +++ modules/nio_char/src/main/java/java/nio/charset/Charset.java (working copy) @@ -108,16 +108,6 @@ // cached Charset table private static HashMap cachedCharsetTable = new HashMap(); - // cached CharsetDecoder table - private static HashMap cachedCharsetDecoderTable = new HashMap(); - - // cached CharsetEncoder table - private static HashMap cachedCharsetEncoderTable = new HashMap(); - - private CharsetEncoder cachedEncoder = null; - - private CharsetDecoder cachedDecoder = null; - static { /* * Create built-in charset provider even if no privilege to access @@ -637,36 +627,19 @@ * the character buffer containing the content to be encoded * @return the result of the encoding */ - synchronized public final ByteBuffer encode(CharBuffer buffer) { - if (cachedEncoder == null) { - cachedEncoder = getCachedCharsetEncoder(canonicalName); - } - - try { - synchronized (cachedEncoder) { - return cachedEncoder.encode(buffer); - } + public final ByteBuffer encode(CharBuffer buffer) { + try + { + return this.newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE) + .encode(buffer); + } catch (CharacterCodingException ex) { throw new Error(ex.getMessage(), ex); } } - /* - * get cached CharsetEncoder by canonical name - */ - private CharsetEncoder getCachedCharsetEncoder(String name) { - synchronized (cachedCharsetEncoderTable) { - CharsetEncoder e = cachedCharsetEncoderTable.get(name); - if (null == e) { - e = this.newEncoder(); - e.onMalformedInput(CodingErrorAction.REPLACE); - e.onUnmappableCharacter(CodingErrorAction.REPLACE); - cachedCharsetEncoderTable.put(name, e); - } - return e; - } - } - /** * Encodes a string and outputs to a byte buffer that is to be returned. *

@@ -695,34 +668,17 @@ * @return a character buffer containing the output of the decoding */ public final CharBuffer decode(ByteBuffer buffer) { - if (cachedDecoder == null) { - cachedDecoder = getCachedCharsetDecoder(canonicalName); - } - try { - synchronized (cachedDecoder) { - return cachedDecoder.decode(buffer); - } - } catch (CharacterCodingException ex) { - throw new Error(ex.getMessage(), ex); - } - } + try { + return this.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE) + .decode(buffer); - /* - * get cached CharsetDecoder by canonical name - */ - private CharsetDecoder getCachedCharsetDecoder(String name) { - synchronized (cachedCharsetDecoderTable) { - CharsetDecoder d = cachedCharsetDecoderTable.get(name); - if (null == d) { - d = this.newDecoder(); - d.onMalformedInput(CodingErrorAction.REPLACE); - d.onUnmappableCharacter(CodingErrorAction.REPLACE); - cachedCharsetDecoderTable.put(name, d); - } - return d; - } - } + } catch (CharacterCodingException ex) { + throw new Error(ex.getMessage(), ex); + } + } /* * ------------------------------------------------------------------- Index: modules/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java =================================================================== --- modules/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java (revision 576863) +++ modules/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java (working copy) @@ -343,32 +343,35 @@ CoderResult result = null; while (true) { result = encode(in, output, false); - checkCoderResult(result); - if (result.isUnderflow()) { + if (result==CoderResult.UNDERFLOW) { break; - } else if (result.isOverflow()) { + } else if (result==CoderResult.OVERFLOW) { output = allocateMore(output); + continue; } + checkCoderResult(result); } result = encode(in, output, true); checkCoderResult(result); while (true) { result = flush(output); - checkCoderResult(result); - if (result.isOverflow()) { + if (result==CoderResult.UNDERFLOW) { + output.flip(); + break; + } else if (result==CoderResult.OVERFLOW) { output = allocateMore(output); - } else { - break; + continue; } - } - + checkCoderResult(result); output.flip(); if (result.isMalformed()) { throw new MalformedInputException(result.length()); } else if (result.isUnmappable()) { throw new UnmappableCharacterException(result.length()); } + break; + } status = FLUSH; return output; } @@ -378,10 +381,9 @@ */ private void checkCoderResult(CoderResult result) throws CharacterCodingException { - if (result.isMalformed() && malformAction == CodingErrorAction.REPORT) { + if (malformAction == CodingErrorAction.REPORT && result.isMalformed() ) { throw new MalformedInputException(result.length()); - } else if (result.isUnmappable() - && unmapAction == CodingErrorAction.REPORT) { + } else if (unmapAction == CodingErrorAction.REPORT && result.isUnmappable()) { throw new UnmappableCharacterException(result.length()); } } @@ -478,16 +480,19 @@ } catch (BufferUnderflowException e) { throw new CoderMalfunctionError(e); } - if (result.isUnderflow()) { - int remaining = in.remaining(); + if (result==CoderResult.UNDERFLOW) { status = endOfInput ? END : ONGOING; - if (endOfInput && remaining > 0) { + if (endOfInput) { + int remaining = in.remaining(); + if( remaining > 0) { result = CoderResult.malformedForLength(remaining); } else { return result; } + } else { + return result; } - if (result.isOverflow()) { + } else if (result==CoderResult.OVERFLOW) { status = endOfInput ? END : ONGOING; return result; } Index: modules/nio_char/src/main/java/org/apache/harmony/niochar/charset/ISO_8859_1.java =================================================================== --- modules/nio_char/src/main/java/org/apache/harmony/niochar/charset/ISO_8859_1.java (revision 576863) +++ modules/nio_char/src/main/java/org/apache/harmony/niochar/charset/ISO_8859_1.java (working copy) @@ -54,52 +54,66 @@ public native int nDecode(char[] array, int arrPosition, int remaining, long outAddr, int absolutePos); - protected CoderResult decodeLoop(ByteBuffer bb, CharBuffer cb){ - int cbRemaining = cb.remaining(); - - if(bb.isDirect() && bb.hasRemaining() && cb.hasArray()){ - int toProceed = bb.remaining(); - boolean throwOverflow = false; - int cbPos = cb.position(); - int bbPos = bb.position(); - if( cbRemaining < toProceed ) { - toProceed = cbRemaining; - throwOverflow = true; - } - int res = nDecode(cb.array(), cb.arrayOffset()+cbPos, toProceed, AddressUtil.getDirectBufferAddress(bb), bbPos); - cb.position(cbPos+res); - bb.position(bbPos+res); - if(throwOverflow) return CoderResult.OVERFLOW; - }else{ - if(bb.hasArray() && cb.hasArray()) { - int rem = bb.remaining(); - rem = cbRemaining >= rem ? rem : cbRemaining; - byte[] arr = bb.array(); - char[] cArr = cb.array(); - int bStart = bb.position(); - int cStart = cb.position(); - int i; - for(i=bStart; i= rem ? rem : cbRemaining; - byte[] arr = new byte[rem]; - bb.get(arr); - char[] cArr = new char[rem]; - for(int i=0; i= rem ? rem : cbRemaining; + byte[] arr = bb.array(); + char[] cArr = cb.array(); + int bStart = bb.position(); + int cStart = cb.position(); + int i; + for (i = bStart; i < bStart + rem; i++) { + cArr[cStart++] = (char) ((int) arr[i] & 0xFF); + } + bb.position(i); + cb.position(cStart); + if (rem == cbRemaining && bb.hasRemaining()) { + return CoderResult.OVERFLOW; + } + return CoderResult.UNDERFLOW; + } else if (bb.isDirect()) { + int toProceed = bbRemaining; + boolean throwOverflow = false; + int cbPos = cb.position(); + int bbPos = bb.position(); + if (cbRemaining < toProceed) { + toProceed = cbRemaining; + throwOverflow = true; + } + int res = nDecode(cb.array(), cb.arrayOffset() + cbPos, + toProceed, AddressUtil.getDirectBufferAddress(bb), + bbPos); + cb.position(cbPos + res); + bb.position(bbPos + res); + if (throwOverflow) { + return CoderResult.OVERFLOW; + } + return CoderResult.UNDERFLOW; + } + } + int rem = bbRemaining; + rem = cbRemaining >= rem ? rem : cbRemaining; + byte[] arr = new byte[rem]; + bb.get(arr); + char[] cArr = new char[rem]; + for (int i = 0; i < rem; i++) { + cArr[i] = (char) ((int) arr[i] & 0xFF); + } + cb.put(cArr); + if (cb.remaining() == 0) { + return CoderResult.OVERFLOW; + } + return CoderResult.UNDERFLOW; } - } + } private final class Encoder extends CharsetEncoder{ private Encoder(Charset cs){ @@ -108,101 +122,116 @@ private native void nEncode(long outAddr, int absolutePos, char[] array, int arrPosition, int[] res); - protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb){ - int bbRemaining = bb.remaining(); - if(bb.isDirect() && cb.hasRemaining() && cb.hasArray()){ - int toProceed = cb.remaining(); - boolean throwOverflow = false; - int cbPos = cb.position(); - int bbPos = bb.position(); - if( bbRemaining < toProceed ) { - toProceed = bbRemaining; - throwOverflow = true; - } - int[] res = {toProceed, 0}; - nEncode(AddressUtil.getDirectBufferAddress(bb), bbPos, cb.array(), cb.arrayOffset()+cbPos, res); - if( res[0] <= 0 ) { - bb.position(bbPos-res[0]); - cb.position(cbPos-res[0]); - if(res[1]!=0) { - if(res[1] < 0) - return CoderResult.malformedForLength(-res[1]); - else - return CoderResult.unmappableForLength(res[1]); - } - }else{ - bb.position(bbPos+res[0]); - cb.position(cbPos+res[0]); - if(throwOverflow) return CoderResult.OVERFLOW; - } - }else{ - if(bb.hasArray() && cb.hasArray()) { - byte[] byteArr = bb.array(); - char[] charArr = cb.array(); - int rem = cb.remaining(); - int byteArrStart = bb.position(); - rem = bbRemaining <= rem ? bbRemaining : rem; - int x; - for(x=cb.position(); x < cb.position()+rem; x++) { - char c = charArr[x]; - if(c > (char)0x00FF){ - if (c >= 0xD800 && c <= 0xDFFF) { - if(x+1 < cb.limit()) { - char c1 = charArr[x+1]; - if(c1 >= 0xD800 && c1 <= 0xDFFF) { - bb.position(byteArrStart); cb.position(x); - return CoderResult.unmappableForLength(2); - } - } else { - bb.position(byteArrStart); cb.position(x); - return CoderResult.UNDERFLOW; - } - bb.position(byteArrStart); cb.position(x); - return CoderResult.malformedForLength(1); - } - bb.position(byteArrStart); cb.position(x); - return CoderResult.unmappableForLength(1); - }else{ - byteArr[byteArrStart++] = (byte)c; - } - } - bb.position(byteArrStart); - cb.position(x); - if(rem == bbRemaining && cb.hasRemaining()) { - return CoderResult.OVERFLOW; - } - } else { - while(cb.hasRemaining()){ - if( bbRemaining == 0 ) return CoderResult.OVERFLOW; - char c = cb.get(); - if(c > (char)0x00FF){ - if (c >= 0xD800 && c <= 0xDFFF) { - if(cb.hasRemaining()) { - char c1 = cb.get(); - if(c1 >= 0xD800 && c1 <= 0xDFFF) { - cb.position(cb.position()-2); - return CoderResult.unmappableForLength(2); - } else { - cb.position(cb.position()-1); - } - } else { - cb.position(cb.position()-1); - return CoderResult.UNDERFLOW; - } - cb.position(cb.position()-1); - return CoderResult.malformedForLength(1); - } - cb.position(cb.position()-1); - return CoderResult.unmappableForLength(1); - }else{ - bb.put((byte)c); - bbRemaining--; - } - } - - } - } - return CoderResult.UNDERFLOW; + protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) { + int cbRemaining = cb.remaining(); + if (cbRemaining == 0) { + return CoderResult.UNDERFLOW; + } + int bbRemaining = bb.remaining(); + boolean cbHasArray = cb.hasArray(); + boolean bbHasArray = bb.hasArray(); + if (cbHasArray) { + if (bbHasArray) { + byte[] byteArr = bb.array(); + char[] charArr = cb.array(); + int byteArrStart = bb.position(); + int rem = bbRemaining <= cbRemaining ? bbRemaining + : cbRemaining; + int cbPos = cb.position(); + int x; + int jchar = 0; + for (x = cbPos; x < cbPos + rem; x++) { + jchar = (int) charArr[x]; + if (jchar <= 0xFF) { + byteArr[byteArrStart++] = (byte) jchar; + } else { + break; + } + } + bb.position(byteArrStart); + cb.position(x); + if (x == cbPos + rem) { + // everything is ok + if (rem == bbRemaining && cb.hasRemaining()) { + return CoderResult.OVERFLOW; + } + return CoderResult.UNDERFLOW; + } + // here is jchar >0xFF + if (jchar >= 0xD800 && jchar <= 0xDFFF) { + if (x + 1 < cb.limit()) { + char c1 = charArr[x + 1]; + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + return CoderResult.unmappableForLength(2); + } + } else { + return CoderResult.UNDERFLOW; + } + return CoderResult.malformedForLength(1); + } + return CoderResult.unmappableForLength(1); + } else if (bb.isDirect()) { + int toProceed = cbRemaining; + boolean throwOverflow = false; + int cbPos = cb.position(); + int bbPos = bb.position(); + if (bbRemaining < toProceed) { + toProceed = bbRemaining; + throwOverflow = true; + } + int[] res = { toProceed, 0 }; + nEncode(AddressUtil.getDirectBufferAddress(bb), bbPos, cb + .array(), cb.arrayOffset() + cbPos, res); + if (res[0] <= 0) { + bb.position(bbPos - res[0]); + cb.position(cbPos - res[0]); + if (res[1] != 0) { + if (res[1] < 0) { + return CoderResult.malformedForLength(-res[1]); + } else { + return CoderResult.unmappableForLength(res[1]); + } + } + } else { + bb.position(bbPos + res[0]); + cb.position(cbPos + res[0]); + if (throwOverflow) { + return CoderResult.OVERFLOW; + } + } + return CoderResult.UNDERFLOW; + } + } + while (cb.hasRemaining()) { + if (bbRemaining == 0) { + return CoderResult.OVERFLOW; + } + char c = cb.get(); + if (c > (char) 0x00FF) { + if (c >= 0xD800 && c <= 0xDFFF) { + if (cb.hasRemaining()) { + char c1 = cb.get(); + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + cb.position(cb.position() - 2); + return CoderResult.unmappableForLength(2); + } else { + cb.position(cb.position() - 1); + } + } else { + cb.position(cb.position() - 1); + return CoderResult.UNDERFLOW; + } + cb.position(cb.position() - 1); + return CoderResult.malformedForLength(1); + } + cb.position(cb.position() - 1); + return CoderResult.unmappableForLength(1); + } else { + bb.put((byte) c); + bbRemaining--; + } + } + return CoderResult.UNDERFLOW; } }