/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core.internal.util; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CodingErrorAction; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.internal.wc.IOExceptionWrapper; /** * @author TMate Software Ltd. * @version 1.3 */ public class SVNCharsetInputStream extends FilterInputStream { private static final int DEFAULT_BUFFER_CAPACITY = 1024; private SVNCharsetConvertor myCharsetConvertor; private byte[] mySourceBuffer; private ByteBuffer myConvertedBuffer; private boolean myEndOfStream; public SVNCharsetInputStream(InputStream in, Charset inputCharset, Charset outputCharset, CodingErrorAction malformedInputAction, CodingErrorAction unmappableCharAction) { super(in); CharsetDecoder decoder = inputCharset.newDecoder(); decoder.onMalformedInput(malformedInputAction); decoder.onUnmappableCharacter(unmappableCharAction); CharsetEncoder encoder = outputCharset.newEncoder(); encoder.onMalformedInput(malformedInputAction); encoder.onUnmappableCharacter(unmappableCharAction); myCharsetConvertor = new SVNCharsetConvertor(decoder, encoder); mySourceBuffer = new byte[DEFAULT_BUFFER_CAPACITY]; myConvertedBuffer = ByteBuffer.allocate(DEFAULT_BUFFER_CAPACITY); myEndOfStream = false; } public int read() throws IOException { byte[] b = new byte[1]; int r = read(b); if (r < 0) { return -1; } return b[0]; } public int read(byte[] b) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { int available = myConvertedBuffer.position(); if (myEndOfStream && available == 0){ return -1; } while (available < len) { int readed = fillBuffer(); try { myConvertedBuffer = myCharsetConvertor.convertChunk(mySourceBuffer, 0, readed, myConvertedBuffer, myEndOfStream); if (myEndOfStream) { myConvertedBuffer = myCharsetConvertor.flush(myConvertedBuffer); break; } } catch (SVNException e) { throw new IOExceptionWrapper(e); } finally { available = myConvertedBuffer.position(); } } myConvertedBuffer.flip(); len = Math.min(myConvertedBuffer.remaining(), len); myConvertedBuffer = myConvertedBuffer.get(b, off, len); myConvertedBuffer = myConvertedBuffer.compact(); return len; } private int fillBuffer() throws IOException { int readed = 0; while (readed < mySourceBuffer.length) { int r = in.read(mySourceBuffer, readed, mySourceBuffer.length - readed); if (r < 0) { myEndOfStream = true; break; } readed += r; } return readed; } public String toString() { final StringBuffer buffer = new StringBuffer(); buffer.append("SVNCharsetInputStream"); buffer.append("[").append(myCharsetConvertor); buffer.append(']'); return buffer.toString(); } }