1. /*
  2. * @(#)CoderResult.java 1.7 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.nio.charset;
  8. import java.lang.ref.WeakReference;
  9. import java.nio.*;
  10. import java.util.Map;
  11. import java.util.HashMap;
  12. /**
  13. * A description of the result state of a coder.
  14. *
  15. * <p> A charset coder, that is, either a decoder or an encoder, consumes bytes
  16. * (or characters) from an input buffer, translates them, and writes the
  17. * resulting characters (or bytes) to an output buffer. A coding process
  18. * terminates for one of four categories of reasons, which are described by
  19. * instances of this class:
  20. *
  21. * <ul>
  22. *
  23. * <li><p> <i>Underflow</i> is reported when there is no more input to be
  24. * processed, or there is insufficient input and additional input is
  25. * required. This condition is represented by the unique result object
  26. * {@link #UNDERFLOW}, whose {@link #isUnderflow() isUnderflow} method
  27. * returns <tt>true</tt>. </p></li>
  28. *
  29. * <li><p> <i>Overflow</i> is reported when there is insufficient room
  30. * remaining in the output buffer. This condition is represented by the
  31. * unique result object {@link #OVERFLOW}, whose {@link #isOverflow()
  32. * isOverflow} method returns <tt>true</tt>. </p></li>
  33. *
  34. * <li><p> A <i>malformed-input error</i> is reported when a sequence of
  35. * input units is not well-formed. Such errors are described by instances of
  36. * this class whose {@link #isMalformed() isMalformed} method returns
  37. * <tt>true</tt> and whose {@link #length() length} method returns the length
  38. * of the malformed sequence. There is one unique instance of this class for
  39. * all malformed-input errors of a given length. </p></li>
  40. *
  41. * <li><p> An <i>unmappable-character error</i> is reported when a sequence
  42. * of input units denotes a character that cannot be represented in the
  43. * output charset. Such errors are described by instances of this class
  44. * whose {@link #isUnmappable() isUnmappable} method returns <tt>true</tt> and
  45. * whose {@link #length() length} method returns the length of the input
  46. * sequence denoting the unmappable character. There is one unique instance
  47. * of this class for all unmappable-character errors of a given length.
  48. * </p></li>
  49. *
  50. * </ul>
  51. *
  52. * For convenience, the {@link #isError() isError} method returns <tt>true</tt>
  53. * for result objects that describe malformed-input and unmappable-character
  54. * errors but <tt>false</tt> for those that describe underflow or overflow
  55. * conditions. </p>
  56. *
  57. *
  58. * @author Mark Reinhold
  59. * @author JSR-51 Expert Group
  60. * @version 1.7, 03/01/23
  61. * @since 1.4
  62. */
  63. public class CoderResult {
  64. private static final int CR_UNDERFLOW = 0;
  65. private static final int CR_OVERFLOW = 1;
  66. private static final int CR_ERROR_MIN = 2;
  67. private static final int CR_MALFORMED = 2;
  68. private static final int CR_UNMAPPABLE = 3;
  69. private static final String[] names
  70. = { "UNDERFLOW", "OVERFLOW", "MALFORMED", "UNMAPPABLE" };
  71. private final int type;
  72. private final int length;
  73. private CoderResult(int type, int length) {
  74. this.type = type;
  75. this.length = length;
  76. }
  77. /**
  78. * Returns a string describing this coder result.
  79. *
  80. * @return A descriptive string
  81. */
  82. public String toString() {
  83. String nm = names[type];
  84. return isError() ? nm + "[" + length + "]" : nm;
  85. }
  86. /**
  87. * Tells whether or not this object describes an underflow condition. </p>
  88. *
  89. * @return <tt>true</tt> if, and only if, this object denotes underflow
  90. */
  91. public boolean isUnderflow() {
  92. return (type == CR_UNDERFLOW);
  93. }
  94. /**
  95. * Tells whether or not this object describes an overflow condition. </p>
  96. *
  97. * @return <tt>true</tt> if, and only if, this object denotes overflow
  98. */
  99. public boolean isOverflow() {
  100. return (type == CR_OVERFLOW);
  101. }
  102. /**
  103. * Tells whether or not this object describes an error condition. </p>
  104. *
  105. * @return <tt>true</tt> if, and only if, this object denotes either a
  106. * malformed-input error or an unmappable-character error
  107. */
  108. public boolean isError() {
  109. return (type >= CR_ERROR_MIN);
  110. }
  111. /**
  112. * Tells whether or not this object describes a malformed-input error.
  113. * </p>
  114. *
  115. * @return <tt>true</tt> if, and only if, this object denotes a
  116. * malformed-input error
  117. */
  118. public boolean isMalformed() {
  119. return (type == CR_MALFORMED);
  120. }
  121. /**
  122. * Tells whether or not this object describes an unmappable-character
  123. * error. </p>
  124. *
  125. * @return <tt>true</tt> if, and only if, this object denotes an
  126. * unmappable-character error
  127. */
  128. public boolean isUnmappable() {
  129. return (type == CR_UNMAPPABLE);
  130. }
  131. /**
  132. * Returns the length of the erroneous input described by this
  133. * object  <i>(optional operation)</i>. </p>
  134. *
  135. * @return The length of the erroneous input, a positive integer
  136. *
  137. * @throws UnsupportedOperationException
  138. * If this object does not describe an error condition, that is,
  139. * if the {@link #isError() isError} does not return <tt>true</tt>
  140. */
  141. public int length() {
  142. if (!isError())
  143. throw new UnsupportedOperationException();
  144. return length;
  145. }
  146. /**
  147. * Result object indicating underflow, meaning that either the input buffer
  148. * has been completely consumed or, if the input buffer is not yet empty,
  149. * that additional input is required. </p>
  150. */
  151. public static final CoderResult UNDERFLOW
  152. = new CoderResult(CR_UNDERFLOW, 0);
  153. /**
  154. * Result object indicating overflow, meaning that there is insufficient
  155. * room in the output buffer. </p>
  156. */
  157. public static final CoderResult OVERFLOW
  158. = new CoderResult(CR_OVERFLOW, 0);
  159. private static abstract class Cache {
  160. private Map cache = null;
  161. protected abstract CoderResult create(int len);
  162. private synchronized CoderResult get(int len) {
  163. if (len <= 0)
  164. throw new IllegalArgumentException("Non-positive length");
  165. Integer k = new Integer(len);
  166. WeakReference w;
  167. CoderResult e = null;
  168. if (cache == null) {
  169. cache = new HashMap();
  170. } else if ((w = (WeakReference)cache.get(k)) != null) {
  171. e = (CoderResult)w.get();
  172. }
  173. if (e == null) {
  174. e = create(len);
  175. cache.put(k, new WeakReference(e));
  176. }
  177. return e;
  178. }
  179. }
  180. private static Cache malformedCache
  181. = new Cache() {
  182. public CoderResult create(int len) {
  183. return new CoderResult(CR_MALFORMED, len);
  184. }};
  185. /**
  186. * Static factory method that returns the unique object describing a
  187. * malformed-input error of the given length. </p>
  188. *
  189. * @return The requested coder-result object
  190. */
  191. public static CoderResult malformedForLength(int length) {
  192. return malformedCache.get(length);
  193. }
  194. private static Cache unmappableCache
  195. = new Cache() {
  196. public CoderResult create(int len) {
  197. return new CoderResult(CR_UNMAPPABLE, len);
  198. }};
  199. /**
  200. * Static factory method that returns the unique result object describing
  201. * an unmappable-character error of the given length. </p>
  202. *
  203. * @return The requested coder-result object
  204. */
  205. public static CoderResult unmappableForLength(int length) {
  206. return unmappableCache.get(length);
  207. }
  208. /**
  209. * Throws an exception appropriate to the result described by this object.
  210. * </p>
  211. *
  212. * @throws BufferUnderflowException
  213. * If this object is {@link #UNDERFLOW}
  214. *
  215. * @throws BufferOverflowException
  216. * If this object is {@link #OVERFLOW}
  217. *
  218. * @throws MalformedInputException
  219. * If this object represents a malformed-input error; the
  220. * exception's length value will be that of this object
  221. *
  222. * @throws UnmappableCharacterException
  223. * If this object represents an unmappable-character error; the
  224. * exceptions length value will be that of this object
  225. */
  226. public void throwException()
  227. throws CharacterCodingException
  228. {
  229. switch (type) {
  230. case CR_UNDERFLOW: throw new BufferUnderflowException();
  231. case CR_OVERFLOW: throw new BufferOverflowException();
  232. case CR_MALFORMED: throw new MalformedInputException(length);
  233. case CR_UNMAPPABLE: throw new UnmappableCharacterException(length);
  234. default:
  235. assert false;
  236. }
  237. }
  238. }