Source for gnu.java.nio.charset.ByteDecodeLoopHelper

   1: /* ByteCharset.java -- Abstract class for generic 1-byte encodings.
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.nio.charset;
  39: 
  40: import java.nio.ByteBuffer;
  41: import java.nio.CharBuffer;
  42: import java.nio.charset.CoderResult;
  43: 
  44: /**
  45:  * Helper class to deal with decoding loops that read a byte at a time
  46:  *
  47:  * @author Ian Rogers
  48:  */
  49: public abstract class ByteDecodeLoopHelper
  50: {
  51:   /**
  52:    * @return can the given byte be encoded
  53:    */
  54:   protected abstract boolean isMappable(byte b);
  55: 
  56:   /**
  57:    * Map the given byte to a char, the given byte is guaranteed to be mappable
  58:    */
  59:   protected abstract char mapToChar(byte b);
  60: 
  61:   /**
  62:    * Encodes one or more characters into one or more bytes, mapping each
  63:    * character to only one byte
  64:    *
  65:    * @param in character buffer to read from
  66:    * @param out byte buffer to write to
  67:    * @return the result state of the encoder
  68:    */
  69:   CoderResult decodeLoop(ByteBuffer in, CharBuffer out)
  70:   {
  71:     if (in.hasArray() && out.hasArray())
  72:       {
  73:         return arrayDecodeLoop(in, out);
  74:       } else
  75:       {
  76:         return normalDecodeLoop(in, out);
  77:       }
  78:   }
  79: 
  80:   /**
  81:    * Encode loop using get and put operations
  82:    */
  83:   private CoderResult normalDecodeLoop(ByteBuffer in, CharBuffer out)
  84:   {
  85:     int outRemaining = out.remaining();
  86:     int inRemaining = in.remaining();
  87:     while (inRemaining > 0 && outRemaining > 0)
  88:       {
  89:         byte b = in.get();
  90:         inRemaining--;
  91: 
  92:         if (!isMappable(b))
  93:           {
  94:             in.position(in.position() - 1);
  95:             return CoderResult.unmappableForLength(1);
  96:           }
  97:         char c = mapToChar(b);
  98:         out.put(c);
  99:         outRemaining--;
 100:       }
 101:     if (inRemaining > 0)
 102:       {
 103:         return CoderResult.OVERFLOW;
 104:       } else
 105:       {
 106:         return CoderResult.UNDERFLOW;
 107:       }
 108:   }
 109: 
 110:   /**
 111:    * Encode loop using array read and write operations
 112:    */
 113:   private CoderResult arrayDecodeLoop(ByteBuffer in, CharBuffer out)
 114:   {
 115:     byte[] inArray = in.array();
 116:     char[] outArray = out.array();
 117:     int inPos = in.arrayOffset() + in.position();
 118:     int outPos = out.arrayOffset() + out.position();
 119:     int inRemaining = in.remaining();
 120:     int outRemaining = out.remaining();
 121:     CoderResult result;
 122: 
 123:         bailOut:
 124:     if (inRemaining <= outRemaining)
 125:       {
 126:         for (int i = 0; i < inRemaining; i++)
 127:           {
 128:             byte b = inArray[inPos];
 129:             inPos++;
 130:             if (!isMappable(b))
 131:               {
 132:                 inPos--;
 133:                 result = CoderResult.unmappableForLength(1);
 134:                                 break bailOut;
 135:               }
 136:             char c = mapToChar(b);
 137:             outArray[outPos] = c;
 138:             outPos++;
 139:           }
 140:         result = CoderResult.UNDERFLOW;
 141:       }
 142:     else
 143:       {
 144:         for (int i = 0; i < outRemaining; i++)
 145:           {
 146:             byte b = inArray[inPos];
 147:             inPos++;
 148:             if (!isMappable(b))
 149:               {
 150:                 inPos--;
 151:                 result = CoderResult.unmappableForLength(1);
 152:                                 break bailOut;
 153:               }
 154:             char c = mapToChar(b);
 155:             outArray[outPos] = c;
 156:             outPos++;
 157:           }
 158:         result = CoderResult.OVERFLOW;
 159:       }
 160:     in.position(inPos - in.arrayOffset());
 161:     out.position(outPos - out.arrayOffset());
 162:     return result;
 163:   }
 164: }