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 */ isMappable(byte b)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 */ mapToChar(byte b)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 */ decodeLoop(ByteBuffer in, CharBuffer out)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 */ normalDecodeLoop(ByteBuffer in, CharBuffer out)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 */ arrayDecodeLoop(ByteBuffer in, CharBuffer out)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 } 165