• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package java.nio.charset;
18 
19 import java.nio.BufferOverflowException;
20 import java.nio.BufferUnderflowException;
21 import java.util.WeakHashMap;
22 
23 /**
24  * Used to indicate the result of encoding/decoding. There are four types of
25  * results:
26  * <ol>
27  * <li>UNDERFLOW indicates that all input has been processed but more input is
28  * required. It is represented by the unique object
29  * <code>CoderResult.UNDERFLOW</code>.
30  * <li>OVERFLOW indicates an insufficient output buffer size. It is represented
31  * by the unique object <code>CoderResult.OVERFLOW</code>.
32  * <li>A malformed-input error indicates that an unrecognizable sequence of
33  * input units has been encountered. Get an instance of this type of result by
34  * calling <code>CoderResult.malformedForLength(int)</code> with the length of
35  * the malformed-input.
36  * <li>An unmappable-character error indicates that a sequence of input units
37  * can not be mapped to the output charset. Get an instance of this type of
38  * result by calling <code>CoderResult.unmappableForLength(int)</code> with
39  * the input sequence size indicating the identity of the unmappable character.
40  * </ol>
41  */
42 public class CoderResult {
43 
44     // indicating underflow error type
45     private static final int TYPE_UNDERFLOW = 1;
46 
47     // indicating overflow error type
48     private static final int TYPE_OVERFLOW = 2;
49 
50     // indicating malformed-input error type
51     private static final int TYPE_MALFORMED_INPUT = 3;
52 
53     // indicating unmappable character error type
54     private static final int TYPE_UNMAPPABLE_CHAR = 4;
55 
56     /**
57      * Result object indicating that there is insufficient data in the
58      * encoding/decoding buffer or that additional data is required.
59      */
60     public static final CoderResult UNDERFLOW = new CoderResult(TYPE_UNDERFLOW,
61             0);
62 
63     /**
64      * Result object used to indicate that the output buffer does not have
65      * enough space available to store the result of the encoding/decoding.
66      */
67     public static final CoderResult OVERFLOW = new CoderResult(TYPE_OVERFLOW, 0);
68 
69     /*
70      * Stores unique result objects for each malformed-input error of a certain
71      * length
72      */
73     private static WeakHashMap<Integer, CoderResult> _malformedErrors = new WeakHashMap<Integer, CoderResult>();
74 
75     /*
76      * Stores unique result objects for each unmappable-character error of a
77      * certain length
78      */
79     private static WeakHashMap<Integer, CoderResult> _unmappableErrors = new WeakHashMap<Integer, CoderResult>();
80 
81     // the type of this result
82     private final int type;
83 
84     // the length of the erroneous input
85     private final int length;
86 
87     /**
88      * Constructs a <code>CoderResult</code> object with its text description.
89      *
90      * @param type
91      *            the type of this result
92      * @param length
93      *            the length of the erroneous input
94      */
CoderResult(int type, int length)95     private CoderResult(int type, int length) {
96         this.type = type;
97         this.length = length;
98     }
99 
100     /**
101      * Gets a <code>CoderResult</code> object indicating a malformed-input
102      * error.
103      *
104      * @param length
105      *            the length of the malformed-input.
106      * @return a <code>CoderResult</code> object indicating a malformed-input
107      *         error.
108      * @throws IllegalArgumentException
109      *             if <code>length</code> is non-positive.
110      */
malformedForLength(int length)111     public static synchronized CoderResult malformedForLength(int length)
112             throws IllegalArgumentException {
113         if (length > 0) {
114             Integer key = Integer.valueOf(length);
115             synchronized (_malformedErrors) {
116                 CoderResult r = _malformedErrors.get(key);
117                 if (r == null) {
118                     r = new CoderResult(TYPE_MALFORMED_INPUT, length);
119                     _malformedErrors.put(key, r);
120                 }
121                 return r;
122             }
123         }
124         throw new IllegalArgumentException("length <= 0: " + length);
125     }
126 
127     /**
128      * Gets a <code>CoderResult</code> object indicating an unmappable
129      * character error.
130      *
131      * @param length
132      *            the length of the input unit sequence denoting the unmappable
133      *            character.
134      * @return a <code>CoderResult</code> object indicating an unmappable
135      *         character error.
136      * @throws IllegalArgumentException
137      *             if <code>length</code> is non-positive.
138      */
unmappableForLength(int length)139     public static synchronized CoderResult unmappableForLength(int length)
140             throws IllegalArgumentException {
141         if (length > 0) {
142             Integer key = Integer.valueOf(length);
143             synchronized (_unmappableErrors) {
144                 CoderResult r = _unmappableErrors.get(key);
145                 if (r == null) {
146                     r = new CoderResult(TYPE_UNMAPPABLE_CHAR, length);
147                     _unmappableErrors.put(key, r);
148                 }
149                 return r;
150             }
151         }
152         throw new IllegalArgumentException("length <= 0: " + length);
153     }
154 
155     /**
156      * Returns true if this result is an underflow condition.
157      *
158      * @return true if an underflow, otherwise false.
159      */
isUnderflow()160     public boolean isUnderflow() {
161         return this.type == TYPE_UNDERFLOW;
162     }
163 
164     /**
165      * Returns true if this result represents a malformed-input error or an
166      * unmappable-character error.
167      *
168      * @return true if this is a malformed-input error or an
169      *         unmappable-character error, otherwise false.
170      */
isError()171     public boolean isError() {
172         return this.type == TYPE_MALFORMED_INPUT
173                 || this.type == TYPE_UNMAPPABLE_CHAR;
174     }
175 
176     /**
177      * Returns true if this result represents a malformed-input error.
178      *
179      * @return true if this is a malformed-input error, otherwise false.
180      */
isMalformed()181     public boolean isMalformed() {
182         return this.type == TYPE_MALFORMED_INPUT;
183     }
184 
185     /**
186      * Returns true if this result is an overflow condition.
187      *
188      * @return true if this is an overflow, otherwise false.
189      */
isOverflow()190     public boolean isOverflow() {
191         return this.type == TYPE_OVERFLOW;
192     }
193 
194     /**
195      * Returns true if this result represents an unmappable-character error.
196      *
197      * @return true if this is an unmappable-character error, otherwise false.
198      */
isUnmappable()199     public boolean isUnmappable() {
200         return this.type == TYPE_UNMAPPABLE_CHAR;
201     }
202 
203     /**
204      * Gets the length of the erroneous input. The length is only meaningful to
205      * a malformed-input error or an unmappable character error.
206      *
207      * @return the length, as an integer, of this object's erroneous input.
208      * @throws UnsupportedOperationException
209      *             if this result is an overflow or underflow.
210      */
length()211     public int length() throws UnsupportedOperationException {
212         if (this.type == TYPE_MALFORMED_INPUT || this.type == TYPE_UNMAPPABLE_CHAR) {
213             return this.length;
214         }
215         throw new UnsupportedOperationException("length meaningless for " + toString());
216     }
217 
218     /**
219      * Throws an exception corresponding to this coder result.
220      *
221      * @throws BufferUnderflowException
222      *             in case this is an underflow.
223      * @throws BufferOverflowException
224      *             in case this is an overflow.
225      * @throws UnmappableCharacterException
226      *             in case this is an unmappable-character error.
227      * @throws MalformedInputException
228      *             in case this is a malformed-input error.
229      * @throws CharacterCodingException
230      *             the default exception.
231      */
throwException()232     public void throwException() throws BufferUnderflowException,
233             BufferOverflowException, UnmappableCharacterException,
234             MalformedInputException, CharacterCodingException {
235         switch (this.type) {
236             case TYPE_UNDERFLOW:
237                 throw new BufferUnderflowException();
238             case TYPE_OVERFLOW:
239                 throw new BufferOverflowException();
240             case TYPE_UNMAPPABLE_CHAR:
241                 throw new UnmappableCharacterException(this.length);
242             case TYPE_MALFORMED_INPUT:
243                 throw new MalformedInputException(this.length);
244             default:
245                 throw new CharacterCodingException();
246         }
247     }
248 
249     /**
250      * Returns a text description of this result.
251      *
252      * @return a text description of this result.
253      */
254     @Override
toString()255     public String toString() {
256         String dsc = null;
257         switch (this.type) {
258             case TYPE_UNDERFLOW:
259                 dsc = "UNDERFLOW error";
260                 break;
261             case TYPE_OVERFLOW:
262                 dsc = "OVERFLOW error";
263                 break;
264             case TYPE_UNMAPPABLE_CHAR:
265                 dsc = "Unmappable-character error with erroneous input length "
266                         + this.length;
267                 break;
268             case TYPE_MALFORMED_INPUT:
269                 dsc = "Malformed-input error with erroneous input length "
270                         + this.length;
271                 break;
272             default:
273                 dsc = "";
274                 break;
275         }
276         return getClass().getName() + "[" + dsc + "]";
277     }
278 }
279