1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package java.nio.charset; 18 19 import java.nio.BufferOverflowException; 20 import java.nio.BufferUnderflowException; 21 import java.util.WeakHashMap; 22 23 /** 24 * Used to indicate the result of encoding/decoding. There are four types of 25 * results: 26 * <ol> 27 * <li>UNDERFLOW indicates that all input has been processed but more input is 28 * required. It is represented by the unique object 29 * <code>CoderResult.UNDERFLOW</code>. 30 * <li>OVERFLOW indicates an insufficient output buffer size. It is represented 31 * by the unique object <code>CoderResult.OVERFLOW</code>. 32 * <li>A malformed-input error indicates that an unrecognizable sequence of 33 * input units has been encountered. Get an instance of this type of result by 34 * calling <code>CoderResult.malformedForLength(int)</code> with the length of 35 * the malformed-input. 36 * <li>An unmappable-character error indicates that a sequence of input units 37 * can not be mapped to the output charset. Get an instance of this type of 38 * result by calling <code>CoderResult.unmappableForLength(int)</code> with 39 * the input sequence size indicating the identity of the unmappable character. 40 * </ol> 41 */ 42 public class CoderResult { 43 44 // indicating underflow error type 45 private static final int TYPE_UNDERFLOW = 1; 46 47 // indicating overflow error type 48 private static final int TYPE_OVERFLOW = 2; 49 50 // indicating malformed-input error type 51 private static final int TYPE_MALFORMED_INPUT = 3; 52 53 // indicating unmappable character error type 54 private static final int TYPE_UNMAPPABLE_CHAR = 4; 55 56 /** 57 * Result object indicating that there is insufficient data in the 58 * encoding/decoding buffer or that additional data is required. 59 */ 60 public static final CoderResult UNDERFLOW = new CoderResult(TYPE_UNDERFLOW, 61 0); 62 63 /** 64 * Result object used to indicate that the output buffer does not have 65 * enough space available to store the result of the encoding/decoding. 66 */ 67 public static final CoderResult OVERFLOW = new CoderResult(TYPE_OVERFLOW, 0); 68 69 /* 70 * Stores unique result objects for each malformed-input error of a certain 71 * length 72 */ 73 private static WeakHashMap<Integer, CoderResult> _malformedErrors = new WeakHashMap<Integer, CoderResult>(); 74 75 /* 76 * Stores unique result objects for each unmappable-character error of a 77 * certain length 78 */ 79 private static WeakHashMap<Integer, CoderResult> _unmappableErrors = new WeakHashMap<Integer, CoderResult>(); 80 81 // the type of this result 82 private final int type; 83 84 // the length of the erroneous input 85 private final int length; 86 87 /** 88 * Constructs a <code>CoderResult</code> object with its text description. 89 * 90 * @param type 91 * the type of this result 92 * @param length 93 * the length of the erroneous input 94 */ CoderResult(int type, int length)95 private CoderResult(int type, int length) { 96 this.type = type; 97 this.length = length; 98 } 99 100 /** 101 * Gets a <code>CoderResult</code> object indicating a malformed-input 102 * error. 103 * 104 * @param length 105 * the length of the malformed-input. 106 * @return a <code>CoderResult</code> object indicating a malformed-input 107 * error. 108 * @throws IllegalArgumentException 109 * if <code>length</code> is non-positive. 110 */ malformedForLength(int length)111 public static synchronized CoderResult malformedForLength(int length) 112 throws IllegalArgumentException { 113 if (length > 0) { 114 Integer key = Integer.valueOf(length); 115 synchronized (_malformedErrors) { 116 CoderResult r = _malformedErrors.get(key); 117 if (r == null) { 118 r = new CoderResult(TYPE_MALFORMED_INPUT, length); 119 _malformedErrors.put(key, r); 120 } 121 return r; 122 } 123 } 124 throw new IllegalArgumentException("length <= 0: " + length); 125 } 126 127 /** 128 * Gets a <code>CoderResult</code> object indicating an unmappable 129 * character error. 130 * 131 * @param length 132 * the length of the input unit sequence denoting the unmappable 133 * character. 134 * @return a <code>CoderResult</code> object indicating an unmappable 135 * character error. 136 * @throws IllegalArgumentException 137 * if <code>length</code> is non-positive. 138 */ unmappableForLength(int length)139 public static synchronized CoderResult unmappableForLength(int length) 140 throws IllegalArgumentException { 141 if (length > 0) { 142 Integer key = Integer.valueOf(length); 143 synchronized (_unmappableErrors) { 144 CoderResult r = _unmappableErrors.get(key); 145 if (r == null) { 146 r = new CoderResult(TYPE_UNMAPPABLE_CHAR, length); 147 _unmappableErrors.put(key, r); 148 } 149 return r; 150 } 151 } 152 throw new IllegalArgumentException("length <= 0: " + length); 153 } 154 155 /** 156 * Returns true if this result is an underflow condition. 157 * 158 * @return true if an underflow, otherwise false. 159 */ isUnderflow()160 public boolean isUnderflow() { 161 return this.type == TYPE_UNDERFLOW; 162 } 163 164 /** 165 * Returns true if this result represents a malformed-input error or an 166 * unmappable-character error. 167 * 168 * @return true if this is a malformed-input error or an 169 * unmappable-character error, otherwise false. 170 */ isError()171 public boolean isError() { 172 return this.type == TYPE_MALFORMED_INPUT 173 || this.type == TYPE_UNMAPPABLE_CHAR; 174 } 175 176 /** 177 * Returns true if this result represents a malformed-input error. 178 * 179 * @return true if this is a malformed-input error, otherwise false. 180 */ isMalformed()181 public boolean isMalformed() { 182 return this.type == TYPE_MALFORMED_INPUT; 183 } 184 185 /** 186 * Returns true if this result is an overflow condition. 187 * 188 * @return true if this is an overflow, otherwise false. 189 */ isOverflow()190 public boolean isOverflow() { 191 return this.type == TYPE_OVERFLOW; 192 } 193 194 /** 195 * Returns true if this result represents an unmappable-character error. 196 * 197 * @return true if this is an unmappable-character error, otherwise false. 198 */ isUnmappable()199 public boolean isUnmappable() { 200 return this.type == TYPE_UNMAPPABLE_CHAR; 201 } 202 203 /** 204 * Gets the length of the erroneous input. The length is only meaningful to 205 * a malformed-input error or an unmappable character error. 206 * 207 * @return the length, as an integer, of this object's erroneous input. 208 * @throws UnsupportedOperationException 209 * if this result is an overflow or underflow. 210 */ length()211 public int length() throws UnsupportedOperationException { 212 if (this.type == TYPE_MALFORMED_INPUT || this.type == TYPE_UNMAPPABLE_CHAR) { 213 return this.length; 214 } 215 throw new UnsupportedOperationException("length meaningless for " + toString()); 216 } 217 218 /** 219 * Throws an exception corresponding to this coder result. 220 * 221 * @throws BufferUnderflowException 222 * in case this is an underflow. 223 * @throws BufferOverflowException 224 * in case this is an overflow. 225 * @throws UnmappableCharacterException 226 * in case this is an unmappable-character error. 227 * @throws MalformedInputException 228 * in case this is a malformed-input error. 229 * @throws CharacterCodingException 230 * the default exception. 231 */ throwException()232 public void throwException() throws BufferUnderflowException, 233 BufferOverflowException, UnmappableCharacterException, 234 MalformedInputException, CharacterCodingException { 235 switch (this.type) { 236 case TYPE_UNDERFLOW: 237 throw new BufferUnderflowException(); 238 case TYPE_OVERFLOW: 239 throw new BufferOverflowException(); 240 case TYPE_UNMAPPABLE_CHAR: 241 throw new UnmappableCharacterException(this.length); 242 case TYPE_MALFORMED_INPUT: 243 throw new MalformedInputException(this.length); 244 default: 245 throw new CharacterCodingException(); 246 } 247 } 248 249 /** 250 * Returns a text description of this result. 251 * 252 * @return a text description of this result. 253 */ 254 @Override toString()255 public String toString() { 256 String dsc = null; 257 switch (this.type) { 258 case TYPE_UNDERFLOW: 259 dsc = "UNDERFLOW error"; 260 break; 261 case TYPE_OVERFLOW: 262 dsc = "OVERFLOW error"; 263 break; 264 case TYPE_UNMAPPABLE_CHAR: 265 dsc = "Unmappable-character error with erroneous input length " 266 + this.length; 267 break; 268 case TYPE_MALFORMED_INPUT: 269 dsc = "Malformed-input error with erroneous input length " 270 + this.length; 271 break; 272 default: 273 dsc = ""; 274 break; 275 } 276 return getClass().getName() + "[" + dsc + "]"; 277 } 278 } 279