/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.nio.charset; import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; import java.util.WeakHashMap; /** * Used to indicate the result of encoding/decoding. There are four types of * results: *
    *
  1. UNDERFLOW indicates that all input has been processed but more input is * required. It is represented by the unique object * CoderResult.UNDERFLOW. *
  2. OVERFLOW indicates an insufficient output buffer size. It is represented * by the unique object CoderResult.OVERFLOW. *
  3. A malformed-input error indicates that an unrecognizable sequence of * input units has been encountered. Get an instance of this type of result by * calling CoderResult.malformedForLength(int) with the length of * the malformed-input. *
  4. An unmappable-character error indicates that a sequence of input units * can not be mapped to the output charset. Get an instance of this type of * result by calling CoderResult.unmappableForLength(int) with * the input sequence size indicating the identity of the unmappable character. *
*/ public class CoderResult { // indicating underflow error type private static final int TYPE_UNDERFLOW = 1; // indicating overflow error type private static final int TYPE_OVERFLOW = 2; // indicating malformed-input error type private static final int TYPE_MALFORMED_INPUT = 3; // indicating unmappable character error type private static final int TYPE_UNMAPPABLE_CHAR = 4; /** * Result object indicating that there is insufficient data in the * encoding/decoding buffer or that additional data is required. */ public static final CoderResult UNDERFLOW = new CoderResult(TYPE_UNDERFLOW, 0); /** * Result object used to indicate that the output buffer does not have * enough space available to store the result of the encoding/decoding. */ public static final CoderResult OVERFLOW = new CoderResult(TYPE_OVERFLOW, 0); /* * Stores unique result objects for each malformed-input error of a certain * length */ private static WeakHashMap _malformedErrors = new WeakHashMap(); /* * Stores unique result objects for each unmappable-character error of a * certain length */ private static WeakHashMap _unmappableErrors = new WeakHashMap(); // the type of this result private final int type; // the length of the erroneous input private final int length; /** * Constructs a CoderResult object with its text description. * * @param type * the type of this result * @param length * the length of the erroneous input */ private CoderResult(int type, int length) { this.type = type; this.length = length; } /** * Gets a CoderResult object indicating a malformed-input * error. * * @param length * the length of the malformed-input. * @return a CoderResult object indicating a malformed-input * error. * @throws IllegalArgumentException * if length is non-positive. */ public static synchronized CoderResult malformedForLength(int length) throws IllegalArgumentException { if (length > 0) { Integer key = Integer.valueOf(length); synchronized (_malformedErrors) { CoderResult r = _malformedErrors.get(key); if (r == null) { r = new CoderResult(TYPE_MALFORMED_INPUT, length); _malformedErrors.put(key, r); } return r; } } throw new IllegalArgumentException("Length must be greater than 0; was " + length); } /** * Gets a CoderResult object indicating an unmappable * character error. * * @param length * the length of the input unit sequence denoting the unmappable * character. * @return a CoderResult object indicating an unmappable * character error. * @throws IllegalArgumentException * if length is non-positive. */ public static synchronized CoderResult unmappableForLength(int length) throws IllegalArgumentException { if (length > 0) { Integer key = Integer.valueOf(length); synchronized (_unmappableErrors) { CoderResult r = _unmappableErrors.get(key); if (r == null) { r = new CoderResult(TYPE_UNMAPPABLE_CHAR, length); _unmappableErrors.put(key, r); } return r; } } throw new IllegalArgumentException("Length must be greater than 0; was " + length); } /** * Returns true if this result is an underflow condition. * * @return true if an underflow, otherwise false. */ public boolean isUnderflow() { return this.type == TYPE_UNDERFLOW; } /** * Returns true if this result represents a malformed-input error or an * unmappable-character error. * * @return true if this is a malformed-input error or an * unmappable-character error, otherwise false. */ public boolean isError() { return this.type == TYPE_MALFORMED_INPUT || this.type == TYPE_UNMAPPABLE_CHAR; } /** * Returns true if this result represents a malformed-input error. * * @return true if this is a malformed-input error, otherwise false. */ public boolean isMalformed() { return this.type == TYPE_MALFORMED_INPUT; } /** * Returns true if this result is an overflow condition. * * @return true if this is an overflow, otherwise false. */ public boolean isOverflow() { return this.type == TYPE_OVERFLOW; } /** * Returns true if this result represents an unmappable-character error. * * @return true if this is an unmappable-character error, otherwise false. */ public boolean isUnmappable() { return this.type == TYPE_UNMAPPABLE_CHAR; } /** * Gets the length of the erroneous input. The length is only meaningful to * a malformed-input error or an unmappable character error. * * @return the length, as an integer, of this object's erroneous input. * @throws UnsupportedOperationException * if this result is an overflow or underflow. */ public int length() throws UnsupportedOperationException { if (this.type == TYPE_MALFORMED_INPUT || this.type == TYPE_UNMAPPABLE_CHAR) { return this.length; } throw new UnsupportedOperationException("length meaningless for " + toString()); } /** * Throws an exception corresponding to this coder result. * * @throws BufferUnderflowException * in case this is an underflow. * @throws BufferOverflowException * in case this is an overflow. * @throws UnmappableCharacterException * in case this is an unmappable-character error. * @throws MalformedInputException * in case this is a malformed-input error. * @throws CharacterCodingException * the default exception. */ public void throwException() throws BufferUnderflowException, BufferOverflowException, UnmappableCharacterException, MalformedInputException, CharacterCodingException { switch (this.type) { case TYPE_UNDERFLOW: throw new BufferUnderflowException(); case TYPE_OVERFLOW: throw new BufferOverflowException(); case TYPE_UNMAPPABLE_CHAR: throw new UnmappableCharacterException(this.length); case TYPE_MALFORMED_INPUT: throw new MalformedInputException(this.length); default: throw new CharacterCodingException(); } } /** * Returns a text description of this result. * * @return a text description of this result. */ @Override public String toString() { String dsc = null; switch (this.type) { case TYPE_UNDERFLOW: dsc = "UNDERFLOW error"; break; case TYPE_OVERFLOW: dsc = "OVERFLOW error"; break; case TYPE_UNMAPPABLE_CHAR: dsc = "Unmappable-character error with erroneous input length " + this.length; break; case TYPE_MALFORMED_INPUT: dsc = "Malformed-input error with erroneous input length " + this.length; break; default: dsc = ""; break; } return getClass().getName() + "[" + dsc + "]"; } }