|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package java.nio.charset; |
|
|
|
import java.nio.BufferOverflowException; |
|
import java.nio.BufferUnderflowException; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.Map; |
|
|
|
/** |
|
* A description of the result state of a coder. |
|
* |
|
* <p> A charset coder, that is, either a decoder or an encoder, consumes bytes |
|
* (or characters) from an input buffer, translates them, and writes the |
|
* resulting characters (or bytes) to an output buffer. A coding process |
|
* terminates for one of four categories of reasons, which are described by |
|
* instances of this class: |
|
* |
|
* <ul> |
|
* |
|
* <li><p> <i>Underflow</i> is reported when there is no more input to be |
|
* processed, or there is insufficient input and additional input is |
|
* required. This condition is represented by the unique result object |
|
* {@link #UNDERFLOW}, whose {@link #isUnderflow() isUnderflow} method |
|
* returns {@code true}. </p></li> |
|
* |
|
* <li><p> <i>Overflow</i> is reported when there is insufficient room |
|
* remaining in the output buffer. This condition is represented by the |
|
* unique result object {@link #OVERFLOW}, whose {@link #isOverflow() |
|
* isOverflow} method returns {@code true}. </p></li> |
|
* |
|
* <li><p> A <i>malformed-input error</i> is reported when a sequence of |
|
* input units is not well-formed. Such errors are described by instances of |
|
* this class whose {@link #isMalformed() isMalformed} method returns |
|
* {@code true} and whose {@link #length() length} method returns the length |
|
* of the malformed sequence. There is one unique instance of this class for |
|
* all malformed-input errors of a given length. </p></li> |
|
* |
|
* <li><p> An <i>unmappable-character error</i> is reported when a sequence |
|
* of input units denotes a character that cannot be represented in the |
|
* output charset. Such errors are described by instances of this class |
|
* whose {@link #isUnmappable() isUnmappable} method returns {@code true} and |
|
* whose {@link #length() length} method returns the length of the input |
|
* sequence denoting the unmappable character. There is one unique instance |
|
* of this class for all unmappable-character errors of a given length. |
|
* </p></li> |
|
* |
|
* </ul> |
|
* |
|
* <p> For convenience, the {@link #isError() isError} method returns {@code true} |
|
* for result objects that describe malformed-input and unmappable-character |
|
* errors but {@code false} for those that describe underflow or overflow |
|
* conditions. </p> |
|
* |
|
* |
|
* @author Mark Reinhold |
|
* @author JSR-51 Expert Group |
|
* @since 1.4 |
|
*/ |
|
|
|
public class CoderResult { |
|
|
|
private static final int CR_UNDERFLOW = 0; |
|
private static final int CR_OVERFLOW = 1; |
|
private static final int CR_ERROR_MIN = 2; |
|
private static final int CR_MALFORMED = 2; |
|
private static final int CR_UNMAPPABLE = 3; |
|
|
|
private static final String[] names |
|
= { "UNDERFLOW", "OVERFLOW", "MALFORMED", "UNMAPPABLE" }; |
|
|
|
private final int type; |
|
private final int length; |
|
|
|
private CoderResult(int type, int length) { |
|
this.type = type; |
|
this.length = length; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String toString() { |
|
String nm = names[type]; |
|
return isError() ? nm + "[" + length + "]" : nm; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isUnderflow() { |
|
return (type == CR_UNDERFLOW); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isOverflow() { |
|
return (type == CR_OVERFLOW); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isError() { |
|
return (type >= CR_ERROR_MIN); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isMalformed() { |
|
return (type == CR_MALFORMED); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isUnmappable() { |
|
return (type == CR_UNMAPPABLE); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int length() { |
|
if (!isError()) |
|
throw new UnsupportedOperationException(); |
|
return length; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static final CoderResult UNDERFLOW |
|
= new CoderResult(CR_UNDERFLOW, 0); |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final CoderResult OVERFLOW |
|
= new CoderResult(CR_OVERFLOW, 0); |
|
|
|
private static final class Cache { |
|
static final Cache INSTANCE = new Cache(); |
|
private Cache() {} |
|
|
|
final Map<Integer, CoderResult> unmappable = new ConcurrentHashMap<>(); |
|
final Map<Integer, CoderResult> malformed = new ConcurrentHashMap<>(); |
|
} |
|
|
|
private static final CoderResult[] malformed4 = new CoderResult[] { |
|
new CoderResult(CR_MALFORMED, 1), |
|
new CoderResult(CR_MALFORMED, 2), |
|
new CoderResult(CR_MALFORMED, 3), |
|
new CoderResult(CR_MALFORMED, 4), |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static CoderResult malformedForLength(int length) { |
|
if (length <= 0) |
|
throw new IllegalArgumentException("Non-positive length"); |
|
if (length <= 4) |
|
return malformed4[length - 1]; |
|
return Cache.INSTANCE.malformed.computeIfAbsent(length, |
|
n -> new CoderResult(CR_MALFORMED, n)); |
|
} |
|
|
|
private static final CoderResult[] unmappable4 = new CoderResult[] { |
|
new CoderResult(CR_UNMAPPABLE, 1), |
|
new CoderResult(CR_UNMAPPABLE, 2), |
|
new CoderResult(CR_UNMAPPABLE, 3), |
|
new CoderResult(CR_UNMAPPABLE, 4), |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static CoderResult unmappableForLength(int length) { |
|
if (length <= 0) |
|
throw new IllegalArgumentException("Non-positive length"); |
|
if (length <= 4) |
|
return unmappable4[length - 1]; |
|
return Cache.INSTANCE.unmappable.computeIfAbsent(length, |
|
n -> new CoderResult(CR_UNMAPPABLE, n)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void throwException() |
|
throws CharacterCodingException |
|
{ |
|
switch (type) { |
|
case CR_UNDERFLOW: throw new BufferUnderflowException(); |
|
case CR_OVERFLOW: throw new BufferOverflowException(); |
|
case CR_MALFORMED: throw new MalformedInputException(length); |
|
case CR_UNMAPPABLE: throw new UnmappableCharacterException(length); |
|
default: |
|
assert false; |
|
} |
|
} |
|
|
|
} |