| /* 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() |
| { |
| } |
| } |