9e01bff779
* java/io/OutputStreamWriter.java (writeChars): Use a 'do' loop. Set 'out.count' earlier. (close): Call setFinished on converter. (flush): Always write work buffer. * java/io/PrintStream.java (writeChars): Do 'do' loop. (close): Call setFinished on converter. Write a 'flush' array. * java/lang/natString.cc (getBytes): Call setFinished on converter. * gnu/gcj/convert/CharsetToBytesAdaptor.java (hasBytes): New field. (write): Set hasBytes. Changed 'finished' logic. (havePendingBytes): Rewrote. (setFinished): New method. * gnu/gcj/convert/UnicodeToBytes.java (setFinished): New method. * testsuite/libjava.lang/RH194522.java: New file. * testsuite/libjava.lang/RH194522.out: New file. From-SVN: r115039
157 lines
3.7 KiB
Java
157 lines
3.7 KiB
Java
/* Copyright (C) 2005, 2006 Free Software Foundation
|
|
|
|
This file is part of libgcj.
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
details. */
|
|
|
|
package gnu.gcj.convert;
|
|
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.CharBuffer;
|
|
import java.nio.charset.Charset;
|
|
import java.nio.charset.CharsetEncoder;
|
|
import java.nio.charset.CodingErrorAction;
|
|
import java.nio.charset.CoderResult;
|
|
import gnu.java.nio.charset.EncodingHelper;
|
|
|
|
/**
|
|
* Adaptor class that allow any {@link Charset} to be used
|
|
* as a UnicodeToBytes converter.
|
|
*/
|
|
public class CharsetToBytesAdaptor extends UnicodeToBytes
|
|
{
|
|
/**
|
|
* The CharsetEncoder that does all the work.
|
|
*/
|
|
private final CharsetEncoder encoder;
|
|
|
|
/**
|
|
* ByteBuffer wrapper for this.buf.
|
|
*/
|
|
private ByteBuffer outBuf;
|
|
|
|
/**
|
|
* True if we've told the CharsetEncoder that there are no more
|
|
* characters available.
|
|
*/
|
|
private boolean closedEncoder;
|
|
|
|
/**
|
|
* True if there are bytes pending in the encoder.
|
|
*/
|
|
private boolean hasBytes;
|
|
|
|
/**
|
|
* True if we're finished.
|
|
*/
|
|
private boolean finished;
|
|
|
|
/**
|
|
* Create a new CharsetToBytesAdaptor for the given Charset.
|
|
*
|
|
* @param cs The Charset.
|
|
*/
|
|
public CharsetToBytesAdaptor(Charset cs)
|
|
{
|
|
this(cs.newEncoder());
|
|
}
|
|
|
|
/**
|
|
* Create a new CharsetToBytesAdaptor for the given CharsetEncoder.
|
|
*
|
|
* @param enc The CharsetEncoder.
|
|
*/
|
|
public CharsetToBytesAdaptor(CharsetEncoder enc)
|
|
{
|
|
encoder = enc;
|
|
// Use default replacments on bad input so that we don't have to
|
|
// deal with errors.
|
|
encoder.onMalformedInput(CodingErrorAction.REPLACE);
|
|
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
|
}
|
|
|
|
/**
|
|
* Return the encoder's name. The backing Charset's name is
|
|
* returned.
|
|
*
|
|
* @return The name.
|
|
*/
|
|
public String getName()
|
|
{
|
|
return EncodingHelper.getOldCanonical(encoder.charset().name());
|
|
}
|
|
|
|
public int write (char[] inbuffer, int inpos, int inlength)
|
|
{
|
|
// Wrap the char array so it can be used by the encoder.
|
|
CharBuffer b = CharBuffer.wrap(inbuffer, inpos, inlength);
|
|
write(b);
|
|
return b.position() - inpos; // Number of chars consumed.
|
|
}
|
|
|
|
public int write (String str, int inpos, int inlength, char work)
|
|
{
|
|
// Wrap the String so it can be used by the encoder.
|
|
CharBuffer b = CharBuffer.wrap(str, inpos, inlength);
|
|
write(b);
|
|
return b.position() - inpos; // Number of chars consumed.
|
|
}
|
|
|
|
/**
|
|
* Encode as much of inBuf as will fit in buf. The number of
|
|
* chars consumed is reflected by the new position of inBuf. The
|
|
* output is put in buf and count is incremented by the number of
|
|
* bytes written.
|
|
*
|
|
* @param inBuf The input.
|
|
*/
|
|
private void write(CharBuffer inBuf)
|
|
{
|
|
// Reuse existing outBuf if it is still wrapping the same array
|
|
// it was created with.
|
|
if (outBuf == null || !outBuf.hasArray() || outBuf.array() != buf)
|
|
outBuf = ByteBuffer.wrap(buf);
|
|
|
|
// Set the current position.
|
|
outBuf.position(count);
|
|
|
|
// Do the conversion.
|
|
CoderResult result = encoder.encode(inBuf, outBuf, closedEncoder);
|
|
hasBytes = result == CoderResult.OVERFLOW;
|
|
if (closedEncoder)
|
|
{
|
|
result = encoder.flush(outBuf);
|
|
if (result == CoderResult.UNDERFLOW)
|
|
finished = true;
|
|
else
|
|
hasBytes = true;
|
|
}
|
|
|
|
// Mark the new end of buf.
|
|
count = outBuf.position();
|
|
}
|
|
|
|
/**
|
|
* Check for cached output in the converter.
|
|
*
|
|
* @return true if there is cached output that has not been
|
|
* written to buf.
|
|
*/
|
|
public boolean havePendingBytes()
|
|
{
|
|
return hasBytes;
|
|
}
|
|
|
|
public void setFinished()
|
|
{
|
|
closedEncoder = true;
|
|
}
|
|
|
|
// These aren't cached.
|
|
public void done()
|
|
{
|
|
}
|
|
}
|