Source for gnu.gcj.convert.CharsetToBytesAdaptor

   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 we're finished.
  43:    */
  44:   private boolean finished;
  45: 
  46:   /**
  47:    * Create a new CharsetToBytesAdaptor for the given Charset.
  48:    *
  49:    * @param cs The Charset.
  50:    */
  51:   public CharsetToBytesAdaptor(Charset cs)
  52:   {
  53:     this(cs.newEncoder());
  54:   }
  55: 
  56:   /**
  57:    * Create a new CharsetToBytesAdaptor for the given CharsetEncoder.
  58:    *
  59:    * @param enc The CharsetEncoder.
  60:    */
  61:   public CharsetToBytesAdaptor(CharsetEncoder enc)
  62:   {
  63:     encoder = enc;
  64:     // Use default replacments on bad input so that we don't have to
  65:     // deal with errors.
  66:     encoder.onMalformedInput(CodingErrorAction.REPLACE);
  67:     encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
  68:   }
  69: 
  70:   /**
  71:    * Return the encoder's name.  The backing Charset's name is
  72:    * returned.
  73:    *
  74:    * @return The name.
  75:    */
  76:   public String getName()
  77:   {
  78:     return EncodingHelper.getOldCanonical(encoder.charset().name());
  79:   }
  80: 
  81:   public int write (char[] inbuffer, int inpos, int inlength)
  82:   {
  83:     // Wrap the char array so it can be used by the encoder.
  84:     CharBuffer b = CharBuffer.wrap(inbuffer, inpos, inlength);
  85:     write(b);
  86:     return b.position() - inpos; // Number of chars consumed.
  87:   }
  88: 
  89:   public int write (String str, int inpos, int inlength, char work)
  90:   {
  91:     // Wrap the String so it can be used by the encoder.
  92:     CharBuffer b = CharBuffer.wrap(str, inpos, inlength);
  93:     write(b);
  94:     return b.position() - inpos; // Number of chars consumed.
  95:   }
  96: 
  97:   /**
  98:    * Encode as much of inBuf as will fit in buf.  The number of
  99:    * chars consumed is reflected by the new position of inBuf.  The
 100:    * output is put in buf and count is incremented by the number of
 101:    * bytes written.
 102:    *
 103:    * @param inBuf The input.
 104:    */
 105:   private void write(CharBuffer inBuf)
 106:   {
 107:     // Reuse existing outBuf if it is still wrapping the same array
 108:     // it was created with.
 109:     if (outBuf == null || !outBuf.hasArray() || outBuf.array() != buf)
 110:       outBuf = ByteBuffer.wrap(buf);
 111: 
 112:     // Set the current position.
 113:     outBuf.position(count);
 114: 
 115:     // If we've already said that there is no more input available,
 116:     // then we simply try to flush again.
 117:     if (closedEncoder)
 118:       {
 119:     CoderResult result = encoder.flush(outBuf);
 120:     if (result == CoderResult.UNDERFLOW)
 121:       finished = true;
 122:        }
 123:     else
 124:       {
 125:     // Do the conversion.  If there are no characters to write,
 126:     // then we are finished.
 127:     closedEncoder = ! inBuf.hasRemaining();
 128:     encoder.encode(inBuf, outBuf, closedEncoder);
 129:       }
 130: 
 131:     // Mark the new end of buf.
 132:     count = outBuf.position();
 133:   }
 134: 
 135:   /**
 136:    * Check for cached output in the converter.
 137:    *
 138:    * @return true if there is cached output that has not been
 139:    * written to buf.
 140:    */
 141:   public boolean havePendingBytes()
 142:   {
 143:     return ! finished;
 144:   }
 145: 
 146:   // These aren't cached.
 147:   public void done()
 148:   {
 149:   }
 150: }