• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.nio.charset;
27 
28 import java.lang.ref.WeakReference;
29 import java.nio.*;
30 import java.util.Map;
31 import java.util.HashMap;
32 
33 
34 /**
35  * A description of the result state of a coder.
36  *
37  * <p> A charset coder, that is, either a decoder or an encoder, consumes bytes
38  * (or characters) from an input buffer, translates them, and writes the
39  * resulting characters (or bytes) to an output buffer.  A coding process
40  * terminates for one of four categories of reasons, which are described by
41  * instances of this class:
42  *
43  * <ul>
44  *
45  *   <li><p> <i>Underflow</i> is reported when there is no more input to be
46  *   processed, or there is insufficient input and additional input is
47  *   required.  This condition is represented by the unique result object
48  *   {@link #UNDERFLOW}, whose {@link #isUnderflow() isUnderflow} method
49  *   returns <tt>true</tt>.  </p></li>
50  *
51  *   <li><p> <i>Overflow</i> is reported when there is insufficient room
52  *   remaining in the output buffer.  This condition is represented by the
53  *   unique result object {@link #OVERFLOW}, whose {@link #isOverflow()
54  *   isOverflow} method returns <tt>true</tt>.  </p></li>
55  *
56  *   <li><p> A <i>malformed-input error</i> is reported when a sequence of
57  *   input units is not well-formed.  Such errors are described by instances of
58  *   this class whose {@link #isMalformed() isMalformed} method returns
59  *   <tt>true</tt> and whose {@link #length() length} method returns the length
60  *   of the malformed sequence.  There is one unique instance of this class for
61  *   all malformed-input errors of a given length.  </p></li>
62  *
63  *   <li><p> An <i>unmappable-character error</i> is reported when a sequence
64  *   of input units denotes a character that cannot be represented in the
65  *   output charset.  Such errors are described by instances of this class
66  *   whose {@link #isUnmappable() isUnmappable} method returns <tt>true</tt> and
67  *   whose {@link #length() length} method returns the length of the input
68  *   sequence denoting the unmappable character.  There is one unique instance
69  *   of this class for all unmappable-character errors of a given length.
70  *   </p></li>
71  *
72  * </ul>
73  *
74  * For convenience, the {@link #isError() isError} method returns <tt>true</tt>
75  * for result objects that describe malformed-input and unmappable-character
76  * errors but <tt>false</tt> for those that describe underflow or overflow
77  * conditions.  </p>
78  *
79  *
80  * @author Mark Reinhold
81  * @author JSR-51 Expert Group
82  * @since 1.4
83  */
84 
85 public class CoderResult {
86 
87     private static final int CR_UNDERFLOW  = 0;
88     private static final int CR_OVERFLOW   = 1;
89     private static final int CR_ERROR_MIN  = 2;
90     private static final int CR_MALFORMED  = 2;
91     private static final int CR_UNMAPPABLE = 3;
92 
93     private static final String[] names
94         = { "UNDERFLOW", "OVERFLOW", "MALFORMED", "UNMAPPABLE" };
95 
96     private final int type;
97     private final int length;
98 
CoderResult(int type, int length)99     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      */
toString()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      */
isUnderflow()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      */
isOverflow()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      */
isError()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      */
isMalformed()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      */
isUnmappable()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&nbsp;&nbsp;<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      */
length()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
186         = new CoderResult(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
193         = new CoderResult(CR_OVERFLOW, 0);
194 
195     private static abstract class Cache {
196 
197         private Map<Integer,WeakReference<CoderResult>> cache = null;
198 
create(int len)199         protected abstract CoderResult create(int len);
200 
get(int len)201         private synchronized CoderResult get(int len) {
202             if (len <= 0)
203                 throw new IllegalArgumentException("Non-positive length");
204             Integer k = new Integer(len);
205             WeakReference<CoderResult> w;
206             CoderResult e = null;
207             if (cache == null) {
208                 cache = new HashMap<Integer,WeakReference<CoderResult>>();
209             } else if ((w = cache.get(k)) != null) {
210                 e = w.get();
211             }
212             if (e == null) {
213                 e = create(len);
214                 cache.put(k, new WeakReference<CoderResult>(e));
215             }
216             return e;
217         }
218 
219     }
220 
221     private static Cache malformedCache
222         = new Cache() {
223                 public CoderResult create(int len) {
224                     return new CoderResult(CR_MALFORMED, len);
225                 }};
226 
227     /**
228      * Static factory method that returns the unique object describing a
229      * malformed-input error of the given length.  </p>
230      *
231      * @return  The requested coder-result object
232      */
malformedForLength(int length)233     public static CoderResult malformedForLength(int length) {
234         return malformedCache.get(length);
235     }
236 
237     private static Cache unmappableCache
238         = new Cache() {
239                 public CoderResult create(int len) {
240                     return new CoderResult(CR_UNMAPPABLE, len);
241                 }};
242 
243     /**
244      * Static factory method that returns the unique result object describing
245      * an unmappable-character error of the given length.  </p>
246      *
247      * @return  The requested coder-result object
248      */
unmappableForLength(int length)249     public static CoderResult unmappableForLength(int length) {
250         return unmappableCache.get(length);
251     }
252 
253     /**
254      * Throws an exception appropriate to the result described by this object.
255      * </p>
256      *
257      * @throws  BufferUnderflowException
258      *          If this object is {@link #UNDERFLOW}
259      *
260      * @throws  BufferOverflowException
261      *          If this object is {@link #OVERFLOW}
262      *
263      * @throws  MalformedInputException
264      *          If this object represents a malformed-input error; the
265      *          exception's length value will be that of this object
266      *
267      * @throws  UnmappableCharacterException
268      *          If this object represents an unmappable-character error; the
269      *          exceptions length value will be that of this object
270      */
throwException()271     public void throwException()
272         throws CharacterCodingException
273     {
274         switch (type) {
275         case CR_UNDERFLOW:   throw new BufferUnderflowException();
276         case CR_OVERFLOW:    throw new BufferOverflowException();
277         case CR_MALFORMED:   throw new MalformedInputException(length);
278         case CR_UNMAPPABLE:  throw new UnmappableCharacterException(length);
279         default:
280             assert false;
281         }
282     }
283 
284 }
285