1 /* 2 * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.nio.charset; 27 28 import java.lang.ref.WeakReference; 29 import java.nio.*; 30 import java.util.Map; 31 import java.util.HashMap; 32 33 34 /** 35 * A description of the result state of a coder. 36 * 37 * <p> A charset coder, that is, either a decoder or an encoder, consumes bytes 38 * (or characters) from an input buffer, translates them, and writes the 39 * resulting characters (or bytes) to an output buffer. A coding process 40 * terminates for one of four categories of reasons, which are described by 41 * instances of this class: 42 * 43 * <ul> 44 * 45 * <li><p> <i>Underflow</i> is reported when there is no more input to be 46 * processed, or there is insufficient input and additional input is 47 * required. This condition is represented by the unique result object 48 * {@link #UNDERFLOW}, whose {@link #isUnderflow() isUnderflow} method 49 * returns <tt>true</tt>. </p></li> 50 * 51 * <li><p> <i>Overflow</i> is reported when there is insufficient room 52 * remaining in the output buffer. This condition is represented by the 53 * unique result object {@link #OVERFLOW}, whose {@link #isOverflow() 54 * isOverflow} method returns <tt>true</tt>. </p></li> 55 * 56 * <li><p> A <i>malformed-input error</i> is reported when a sequence of 57 * input units is not well-formed. Such errors are described by instances of 58 * this class whose {@link #isMalformed() isMalformed} method returns 59 * <tt>true</tt> and whose {@link #length() length} method returns the length 60 * of the malformed sequence. There is one unique instance of this class for 61 * all malformed-input errors of a given length. </p></li> 62 * 63 * <li><p> An <i>unmappable-character error</i> is reported when a sequence 64 * of input units denotes a character that cannot be represented in the 65 * output charset. Such errors are described by instances of this class 66 * whose {@link #isUnmappable() isUnmappable} method returns <tt>true</tt> and 67 * whose {@link #length() length} method returns the length of the input 68 * sequence denoting the unmappable character. There is one unique instance 69 * of this class for all unmappable-character errors of a given length. 70 * </p></li> 71 * 72 * </ul> 73 * 74 * For convenience, the {@link #isError() isError} method returns <tt>true</tt> 75 * for result objects that describe malformed-input and unmappable-character 76 * errors but <tt>false</tt> for those that describe underflow or overflow 77 * conditions. </p> 78 * 79 * 80 * @author Mark Reinhold 81 * @author JSR-51 Expert Group 82 * @since 1.4 83 */ 84 85 public class CoderResult { 86 87 private static final int CR_UNDERFLOW = 0; 88 private static final int CR_OVERFLOW = 1; 89 private static final int CR_ERROR_MIN = 2; 90 private static final int CR_MALFORMED = 2; 91 private static final int CR_UNMAPPABLE = 3; 92 93 private static final String[] names 94 = { "UNDERFLOW", "OVERFLOW", "MALFORMED", "UNMAPPABLE" }; 95 96 private final int type; 97 private final int length; 98 CoderResult(int type, int length)99 private CoderResult(int type, int length) { 100 this.type = type; 101 this.length = length; 102 } 103 104 /** 105 * Returns a string describing this coder result. 106 * 107 * @return A descriptive string 108 */ toString()109 public String toString() { 110 String nm = names[type]; 111 return isError() ? nm + "[" + length + "]" : nm; 112 } 113 114 /** 115 * Tells whether or not this object describes an underflow condition. </p> 116 * 117 * @return <tt>true</tt> if, and only if, this object denotes underflow 118 */ isUnderflow()119 public boolean isUnderflow() { 120 return (type == CR_UNDERFLOW); 121 } 122 123 /** 124 * Tells whether or not this object describes an overflow condition. </p> 125 * 126 * @return <tt>true</tt> if, and only if, this object denotes overflow 127 */ isOverflow()128 public boolean isOverflow() { 129 return (type == CR_OVERFLOW); 130 } 131 132 /** 133 * Tells whether or not this object describes an error condition. </p> 134 * 135 * @return <tt>true</tt> if, and only if, this object denotes either a 136 * malformed-input error or an unmappable-character error 137 */ isError()138 public boolean isError() { 139 return (type >= CR_ERROR_MIN); 140 } 141 142 /** 143 * Tells whether or not this object describes a malformed-input error. 144 * </p> 145 * 146 * @return <tt>true</tt> if, and only if, this object denotes a 147 * malformed-input error 148 */ isMalformed()149 public boolean isMalformed() { 150 return (type == CR_MALFORMED); 151 } 152 153 /** 154 * Tells whether or not this object describes an unmappable-character 155 * error. </p> 156 * 157 * @return <tt>true</tt> if, and only if, this object denotes an 158 * unmappable-character error 159 */ isUnmappable()160 public boolean isUnmappable() { 161 return (type == CR_UNMAPPABLE); 162 } 163 164 /** 165 * Returns the length of the erroneous input described by this 166 * object <i>(optional operation)</i>. </p> 167 * 168 * @return The length of the erroneous input, a positive integer 169 * 170 * @throws UnsupportedOperationException 171 * If this object does not describe an error condition, that is, 172 * if the {@link #isError() isError} does not return <tt>true</tt> 173 */ length()174 public int length() { 175 if (!isError()) 176 throw new UnsupportedOperationException(); 177 return length; 178 } 179 180 /** 181 * Result object indicating underflow, meaning that either the input buffer 182 * has been completely consumed or, if the input buffer is not yet empty, 183 * that additional input is required. </p> 184 */ 185 public static final CoderResult UNDERFLOW 186 = new CoderResult(CR_UNDERFLOW, 0); 187 188 /** 189 * Result object indicating overflow, meaning that there is insufficient 190 * room in the output buffer. </p> 191 */ 192 public static final CoderResult OVERFLOW 193 = new CoderResult(CR_OVERFLOW, 0); 194 195 private static abstract class Cache { 196 197 private Map<Integer,WeakReference<CoderResult>> cache = null; 198 create(int len)199 protected abstract CoderResult create(int len); 200 get(int len)201 private synchronized CoderResult get(int len) { 202 if (len <= 0) 203 throw new IllegalArgumentException("Non-positive length"); 204 Integer k = new Integer(len); 205 WeakReference<CoderResult> w; 206 CoderResult e = null; 207 if (cache == null) { 208 cache = new HashMap<Integer,WeakReference<CoderResult>>(); 209 } else if ((w = cache.get(k)) != null) { 210 e = w.get(); 211 } 212 if (e == null) { 213 e = create(len); 214 cache.put(k, new WeakReference<CoderResult>(e)); 215 } 216 return e; 217 } 218 219 } 220 221 private static Cache malformedCache 222 = new Cache() { 223 public CoderResult create(int len) { 224 return new CoderResult(CR_MALFORMED, len); 225 }}; 226 227 /** 228 * Static factory method that returns the unique object describing a 229 * malformed-input error of the given length. </p> 230 * 231 * @return The requested coder-result object 232 */ malformedForLength(int length)233 public static CoderResult malformedForLength(int length) { 234 return malformedCache.get(length); 235 } 236 237 private static Cache unmappableCache 238 = new Cache() { 239 public CoderResult create(int len) { 240 return new CoderResult(CR_UNMAPPABLE, len); 241 }}; 242 243 /** 244 * Static factory method that returns the unique result object describing 245 * an unmappable-character error of the given length. </p> 246 * 247 * @return The requested coder-result object 248 */ unmappableForLength(int length)249 public static CoderResult unmappableForLength(int length) { 250 return unmappableCache.get(length); 251 } 252 253 /** 254 * Throws an exception appropriate to the result described by this object. 255 * </p> 256 * 257 * @throws BufferUnderflowException 258 * If this object is {@link #UNDERFLOW} 259 * 260 * @throws BufferOverflowException 261 * If this object is {@link #OVERFLOW} 262 * 263 * @throws MalformedInputException 264 * If this object represents a malformed-input error; the 265 * exception's length value will be that of this object 266 * 267 * @throws UnmappableCharacterException 268 * If this object represents an unmappable-character error; the 269 * exceptions length value will be that of this object 270 */ throwException()271 public void throwException() 272 throws CharacterCodingException 273 { 274 switch (type) { 275 case CR_UNDERFLOW: throw new BufferUnderflowException(); 276 case CR_OVERFLOW: throw new BufferOverflowException(); 277 case CR_MALFORMED: throw new MalformedInputException(length); 278 case CR_UNMAPPABLE: throw new UnmappableCharacterException(length); 279 default: 280 assert false; 281 } 282 } 283 284 } 285