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 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:    */
  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:    */
  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:    */
  81:   public String getName()
  82:   {
  83:     return EncodingHelper.getOldCanonical(encoder.charset().name());
  84:   }
  85: 
  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: 
  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:    */
 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:    */
 142:   public boolean havePendingBytes()
 143:   {
 144:     return hasBytes;
 145:   }
 146: 
 147:   public void setFinished()
 148:   {
 149:     closedEncoder = true;
 150:   }
 151: 
 152:   // These aren't cached.
 153:   public void done()
 154:   {
 155:   }
 156: }