1 /* Copyright (C) 2005, 2006 Free Software Foundation 2 3 This file is part of libgcj. 4 5 This software is copyrighted work licensed under the terms of the 6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for 7 details. */ 8 9 package gnu.gcj.convert; 10 11 import java.nio.ByteBuffer; 12 import java.nio.CharBuffer; 13 import java.nio.charset.Charset; 14 import java.nio.charset.CharsetEncoder; 15 import java.nio.charset.CodingErrorAction; 16 import java.nio.charset.CoderResult; 17 import gnu.java.nio.charset.EncodingHelper; 18 19 /** 20 * Adaptor class that allow any {@link Charset} to be used 21 * as a UnicodeToBytes converter. 22 */ 23 public class CharsetToBytesAdaptor extends UnicodeToBytes 24 { 25 /** 26 * The CharsetEncoder that does all the work. 27 */ 28 private final CharsetEncoder encoder; 29 30 /** 31 * ByteBuffer wrapper for this.buf. 32 */ 33 private ByteBuffer outBuf; 34 35 /** 36 * True if we've told the CharsetEncoder that there are no more 37 * characters available. 38 */ 39 private boolean closedEncoder; 40 41 /** 42 * True if there are bytes pending in the encoder. 43 */ 44 private boolean hasBytes; 45 46 /** 47 * True if we're finished. 48 */ 49 private boolean finished; 50 51 /** 52 * Create a new CharsetToBytesAdaptor for the given Charset. 53 * 54 * @param cs The Charset. 55 */ CharsetToBytesAdaptor(Charset cs)56 public CharsetToBytesAdaptor(Charset cs) 57 { 58 this(cs.newEncoder()); 59 } 60 61 /** 62 * Create a new CharsetToBytesAdaptor for the given CharsetEncoder. 63 * 64 * @param enc The CharsetEncoder. 65 */ CharsetToBytesAdaptor(CharsetEncoder enc)66 public CharsetToBytesAdaptor(CharsetEncoder enc) 67 { 68 encoder = enc; 69 // Use default replacments on bad input so that we don't have to 70 // deal with errors. 71 encoder.onMalformedInput(CodingErrorAction.REPLACE); 72 encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); 73 } 74 75 /** 76 * Return the encoder's name. The backing Charset's name is 77 * returned. 78 * 79 * @return The name. 80 */ getName()81 public String getName() 82 { 83 return EncodingHelper.getOldCanonical(encoder.charset().name()); 84 } 85 write(char[] inbuffer, int inpos, int inlength)86 public int write (char[] inbuffer, int inpos, int inlength) 87 { 88 // Wrap the char array so it can be used by the encoder. 89 CharBuffer b = CharBuffer.wrap(inbuffer, inpos, inlength); 90 write(b); 91 return b.position() - inpos; // Number of chars consumed. 92 } 93 write(String str, int inpos, int inlength, char work)94 public int write (String str, int inpos, int inlength, char work) 95 { 96 // Wrap the String so it can be used by the encoder. 97 CharBuffer b = CharBuffer.wrap(str, inpos, inlength); 98 write(b); 99 return b.position() - inpos; // Number of chars consumed. 100 } 101 102 /** 103 * Encode as much of inBuf as will fit in buf. The number of 104 * chars consumed is reflected by the new position of inBuf. The 105 * output is put in buf and count is incremented by the number of 106 * bytes written. 107 * 108 * @param inBuf The input. 109 */ write(CharBuffer inBuf)110 private void write(CharBuffer inBuf) 111 { 112 // Reuse existing outBuf if it is still wrapping the same array 113 // it was created with. 114 if (outBuf == null || !outBuf.hasArray() || outBuf.array() != buf) 115 outBuf = ByteBuffer.wrap(buf); 116 117 // Set the current position. 118 outBuf.position(count); 119 120 // Do the conversion. 121 CoderResult result = encoder.encode(inBuf, outBuf, closedEncoder); 122 hasBytes = result == CoderResult.OVERFLOW; 123 if (closedEncoder) 124 { 125 result = encoder.flush(outBuf); 126 if (result == CoderResult.UNDERFLOW) 127 finished = true; 128 else 129 hasBytes = true; 130 } 131 132 // Mark the new end of buf. 133 count = outBuf.position(); 134 } 135 136 /** 137 * Check for cached output in the converter. 138 * 139 * @return true if there is cached output that has not been 140 * written to buf. 141 */ havePendingBytes()142 public boolean havePendingBytes() 143 { 144 return hasBytes; 145 } 146 setFinished()147 public void setFinished() 148 { 149 closedEncoder = true; 150 } 151 152 // These aren't cached. done()153 public void done() 154 { 155 } 156 } 157