|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package java.nio.charset; |
|
|
|
import java.lang.ref.WeakReference; |
|
import java.nio.*; |
|
import java.util.Map; |
|
import java.util.HashMap; |
|
|
|
|
|
/** |
|
* 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 <tt>true</tt>. </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 <tt>true</tt>. </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 |
|
* <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> |
|
* for result objects that describe malformed-input and unmappable-character |
|
* errors but <tt>false</tt> 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 abstract class Cache { |
|
|
|
private Map<Integer,WeakReference<CoderResult>> cache = null; |
|
|
|
protected abstract CoderResult create(int len); |
|
|
|
private synchronized CoderResult get(int len) { |
|
if (len <= 0) |
|
throw new IllegalArgumentException("Non-positive length"); |
|
Integer k = new Integer(len); |
|
WeakReference<CoderResult> w; |
|
CoderResult e = null; |
|
if (cache == null) { |
|
cache = new HashMap<Integer,WeakReference<CoderResult>>(); |
|
} else if ((w = cache.get(k)) != null) { |
|
e = w.get(); |
|
} |
|
if (e == null) { |
|
e = create(len); |
|
cache.put(k, new WeakReference<CoderResult>(e)); |
|
} |
|
return e; |
|
} |
|
|
|
} |
|
|
|
private static Cache malformedCache |
|
= new Cache() { |
|
public CoderResult create(int len) { |
|
return new CoderResult(CR_MALFORMED, len); |
|
}}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static CoderResult malformedForLength(int length) { |
|
return malformedCache.get(length); |
|
} |
|
|
|
private static Cache unmappableCache |
|
= new Cache() { |
|
public CoderResult create(int len) { |
|
return new CoderResult(CR_UNMAPPABLE, len); |
|
}}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static CoderResult unmappableForLength(int length) { |
|
return unmappableCache.get(length); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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; |
|
} |
|
} |
|
|
|
} |