001 /*
002 * Copyright 2001-2002 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.nio.charset;
027
028 import java.lang.ref.WeakReference;
029 import java.nio.*;
030 import java.util.Map;
031 import java.util.HashMap;
032
033 /**
034 * A description of the result state of a coder.
035 *
036 * <p> A charset coder, that is, either a decoder or an encoder, consumes bytes
037 * (or characters) from an input buffer, translates them, and writes the
038 * resulting characters (or bytes) to an output buffer. A coding process
039 * terminates for one of four categories of reasons, which are described by
040 * instances of this class:
041 *
042 * <ul>
043 *
044 * <li><p> <i>Underflow</i> is reported when there is no more input to be
045 * processed, or there is insufficient input and additional input is
046 * required. This condition is represented by the unique result object
047 * {@link #UNDERFLOW}, whose {@link #isUnderflow() isUnderflow} method
048 * returns <tt>true</tt>. </p></li>
049 *
050 * <li><p> <i>Overflow</i> is reported when there is insufficient room
051 * remaining in the output buffer. This condition is represented by the
052 * unique result object {@link #OVERFLOW}, whose {@link #isOverflow()
053 * isOverflow} method returns <tt>true</tt>. </p></li>
054 *
055 * <li><p> A <i>malformed-input error</i> is reported when a sequence of
056 * input units is not well-formed. Such errors are described by instances of
057 * this class whose {@link #isMalformed() isMalformed} method returns
058 * <tt>true</tt> and whose {@link #length() length} method returns the length
059 * of the malformed sequence. There is one unique instance of this class for
060 * all malformed-input errors of a given length. </p></li>
061 *
062 * <li><p> An <i>unmappable-character error</i> is reported when a sequence
063 * of input units denotes a character that cannot be represented in the
064 * output charset. Such errors are described by instances of this class
065 * whose {@link #isUnmappable() isUnmappable} method returns <tt>true</tt> and
066 * whose {@link #length() length} method returns the length of the input
067 * sequence denoting the unmappable character. There is one unique instance
068 * of this class for all unmappable-character errors of a given length.
069 * </p></li>
070 *
071 * </ul>
072 *
073 * For convenience, the {@link #isError() isError} method returns <tt>true</tt>
074 * for result objects that describe malformed-input and unmappable-character
075 * errors but <tt>false</tt> for those that describe underflow or overflow
076 * conditions. </p>
077 *
078 *
079 * @author Mark Reinhold
080 * @author JSR-51 Expert Group
081 * @version 1.15, 07/05/05
082 * @since 1.4
083 */
084
085 public class CoderResult {
086
087 private static final int CR_UNDERFLOW = 0;
088 private static final int CR_OVERFLOW = 1;
089 private static final int CR_ERROR_MIN = 2;
090 private static final int CR_MALFORMED = 2;
091 private static final int CR_UNMAPPABLE = 3;
092
093 private static final String[] names = { "UNDERFLOW", "OVERFLOW",
094 "MALFORMED", "UNMAPPABLE" };
095
096 private final int type;
097 private final int length;
098
099 private CoderResult(int type, int length) {
100 this .type = type;
101 this .length = length;
102 }
103
104 /**
105 * Returns a string describing this coder result.
106 *
107 * @return A descriptive string
108 */
109 public String toString() {
110 String nm = names[type];
111 return isError() ? nm + "[" + length + "]" : nm;
112 }
113
114 /**
115 * Tells whether or not this object describes an underflow condition. </p>
116 *
117 * @return <tt>true</tt> if, and only if, this object denotes underflow
118 */
119 public boolean isUnderflow() {
120 return (type == CR_UNDERFLOW);
121 }
122
123 /**
124 * Tells whether or not this object describes an overflow condition. </p>
125 *
126 * @return <tt>true</tt> if, and only if, this object denotes overflow
127 */
128 public boolean isOverflow() {
129 return (type == CR_OVERFLOW);
130 }
131
132 /**
133 * Tells whether or not this object describes an error condition. </p>
134 *
135 * @return <tt>true</tt> if, and only if, this object denotes either a
136 * malformed-input error or an unmappable-character error
137 */
138 public boolean isError() {
139 return (type >= CR_ERROR_MIN);
140 }
141
142 /**
143 * Tells whether or not this object describes a malformed-input error.
144 * </p>
145 *
146 * @return <tt>true</tt> if, and only if, this object denotes a
147 * malformed-input error
148 */
149 public boolean isMalformed() {
150 return (type == CR_MALFORMED);
151 }
152
153 /**
154 * Tells whether or not this object describes an unmappable-character
155 * error. </p>
156 *
157 * @return <tt>true</tt> if, and only if, this object denotes an
158 * unmappable-character error
159 */
160 public boolean isUnmappable() {
161 return (type == CR_UNMAPPABLE);
162 }
163
164 /**
165 * Returns the length of the erroneous input described by this
166 * object <i>(optional operation)</i>. </p>
167 *
168 * @return The length of the erroneous input, a positive integer
169 *
170 * @throws UnsupportedOperationException
171 * If this object does not describe an error condition, that is,
172 * if the {@link #isError() isError} does not return <tt>true</tt>
173 */
174 public int length() {
175 if (!isError())
176 throw new UnsupportedOperationException();
177 return length;
178 }
179
180 /**
181 * Result object indicating underflow, meaning that either the input buffer
182 * has been completely consumed or, if the input buffer is not yet empty,
183 * that additional input is required. </p>
184 */
185 public static final CoderResult UNDERFLOW = new CoderResult(
186 CR_UNDERFLOW, 0);
187
188 /**
189 * Result object indicating overflow, meaning that there is insufficient
190 * room in the output buffer. </p>
191 */
192 public static final CoderResult OVERFLOW = new CoderResult(
193 CR_OVERFLOW, 0);
194
195 private static abstract class Cache {
196
197 private Map cache = null;
198
199 protected abstract CoderResult create(int len);
200
201 private synchronized CoderResult get(int len) {
202 if (len <= 0)
203 throw new IllegalArgumentException(
204 "Non-positive length");
205 Integer k = new Integer(len);
206 WeakReference w;
207 CoderResult e = null;
208 if (cache == null) {
209 cache = new HashMap();
210 } else if ((w = (WeakReference) cache.get(k)) != null) {
211 e = (CoderResult) w.get();
212 }
213 if (e == null) {
214 e = create(len);
215 cache.put(k, new WeakReference(e));
216 }
217 return e;
218 }
219
220 }
221
222 private static Cache malformedCache = new Cache() {
223 public CoderResult create(int len) {
224 return new CoderResult(CR_MALFORMED, len);
225 }
226 };
227
228 /**
229 * Static factory method that returns the unique object describing a
230 * malformed-input error of the given length. </p>
231 *
232 * @return The requested coder-result object
233 */
234 public static CoderResult malformedForLength(int length) {
235 return malformedCache.get(length);
236 }
237
238 private static Cache unmappableCache = new Cache() {
239 public CoderResult create(int len) {
240 return new CoderResult(CR_UNMAPPABLE, len);
241 }
242 };
243
244 /**
245 * Static factory method that returns the unique result object describing
246 * an unmappable-character error of the given length. </p>
247 *
248 * @return The requested coder-result object
249 */
250 public static CoderResult unmappableForLength(int length) {
251 return unmappableCache.get(length);
252 }
253
254 /**
255 * Throws an exception appropriate to the result described by this object.
256 * </p>
257 *
258 * @throws BufferUnderflowException
259 * If this object is {@link #UNDERFLOW}
260 *
261 * @throws BufferOverflowException
262 * If this object is {@link #OVERFLOW}
263 *
264 * @throws MalformedInputException
265 * If this object represents a malformed-input error; the
266 * exception's length value will be that of this object
267 *
268 * @throws UnmappableCharacterException
269 * If this object represents an unmappable-character error; the
270 * exceptions length value will be that of this object
271 */
272 public void throwException() throws CharacterCodingException {
273 switch (type) {
274 case CR_UNDERFLOW:
275 throw new BufferUnderflowException();
276 case CR_OVERFLOW:
277 throw new BufferOverflowException();
278 case CR_MALFORMED:
279 throw new MalformedInputException(length);
280 case CR_UNMAPPABLE:
281 throw new UnmappableCharacterException(length);
282 default:
283 assert false;
284 }
285 }
286
287 }
|