1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/nio/charset/CharsetDecoder.java Thu Oct 03 15:40:35 2013 +0200
1.3 @@ -0,0 +1,972 @@
1.4 +/*
1.5 + * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
1.6 + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
1.7 + *
1.8 + *
1.9 + *
1.10 + *
1.11 + *
1.12 + *
1.13 + *
1.14 + *
1.15 + *
1.16 + *
1.17 + *
1.18 + *
1.19 + *
1.20 + *
1.21 + *
1.22 + *
1.23 + *
1.24 + *
1.25 + *
1.26 + *
1.27 + */
1.28 +
1.29 +// -- This file was mechanically generated: Do not edit! -- //
1.30 +
1.31 +package java.nio.charset;
1.32 +
1.33 +import java.nio.Buffer;
1.34 +import java.nio.ByteBuffer;
1.35 +import java.nio.CharBuffer;
1.36 +import java.nio.BufferOverflowException;
1.37 +import java.nio.BufferUnderflowException;
1.38 +import java.lang.ref.WeakReference;
1.39 +import java.nio.charset.CoderMalfunctionError; // javadoc
1.40 +
1.41 +
1.42 +/**
1.43 + * An engine that can transform a sequence of bytes in a specific charset into a sequence of
1.44 + * sixteen-bit Unicode characters.
1.45 + *
1.46 + * <a name="steps">
1.47 + *
1.48 + * <p> The input byte sequence is provided in a byte buffer or a series
1.49 + * of such buffers. The output character sequence is written to a character buffer
1.50 + * or a series of such buffers. A decoder should always be used by making
1.51 + * the following sequence of method invocations, hereinafter referred to as a
1.52 + * <i>decoding operation</i>:
1.53 + *
1.54 + * <ol>
1.55 + *
1.56 + * <li><p> Reset the decoder via the {@link #reset reset} method, unless it
1.57 + * has not been used before; </p></li>
1.58 + *
1.59 + * <li><p> Invoke the {@link #decode decode} method zero or more times, as
1.60 + * long as additional input may be available, passing <tt>false</tt> for the
1.61 + * <tt>endOfInput</tt> argument and filling the input buffer and flushing the
1.62 + * output buffer between invocations; </p></li>
1.63 + *
1.64 + * <li><p> Invoke the {@link #decode decode} method one final time, passing
1.65 + * <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
1.66 + *
1.67 + * <li><p> Invoke the {@link #flush flush} method so that the decoder can
1.68 + * flush any internal state to the output buffer. </p></li>
1.69 + *
1.70 + * </ol>
1.71 + *
1.72 + * Each invocation of the {@link #decode decode} method will decode as many
1.73 + * bytes as possible from the input buffer, writing the resulting characters
1.74 + * to the output buffer. The {@link #decode decode} method returns when more
1.75 + * input is required, when there is not enough room in the output buffer, or
1.76 + * when a decoding error has occurred. In each case a {@link CoderResult}
1.77 + * object is returned to describe the reason for termination. An invoker can
1.78 + * examine this object and fill the input buffer, flush the output buffer, or
1.79 + * attempt to recover from a decoding error, as appropriate, and try again.
1.80 + *
1.81 + * <a name="ce">
1.82 + *
1.83 + * <p> There are two general types of decoding errors. If the input byte
1.84 + * sequence is not legal for this charset then the input is considered <i>malformed</i>. If
1.85 + * the input byte sequence is legal but cannot be mapped to a valid
1.86 + * Unicode character then an <i>unmappable character</i> has been encountered.
1.87 + *
1.88 + * <a name="cae">
1.89 + *
1.90 + * <p> How a decoding error is handled depends upon the action requested for
1.91 + * that type of error, which is described by an instance of the {@link
1.92 + * CodingErrorAction} class. The possible error actions are to {@link
1.93 + * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
1.94 + * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
1.95 + * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
1.96 + * </code>replace<code>} the erroneous input with the current value of the
1.97 + * replacement string. The replacement
1.98 + *
1.99 +
1.100 +
1.101 +
1.102 +
1.103 +
1.104 + * has the initial value <tt>"\uFFFD"</tt>;
1.105 +
1.106 + *
1.107 + * its value may be changed via the {@link #replaceWith(java.lang.String)
1.108 + * replaceWith} method.
1.109 + *
1.110 + * <p> The default action for malformed-input and unmappable-character errors
1.111 + * is to {@link CodingErrorAction#REPORT </code>report<code>} them. The
1.112 + * malformed-input error action may be changed via the {@link
1.113 + * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
1.114 + * unmappable-character action may be changed via the {@link
1.115 + * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
1.116 + *
1.117 + * <p> This class is designed to handle many of the details of the decoding
1.118 + * process, including the implementation of error actions. A decoder for a
1.119 + * specific charset, which is a concrete subclass of this class, need only
1.120 + * implement the abstract {@link #decodeLoop decodeLoop} method, which
1.121 + * encapsulates the basic decoding loop. A subclass that maintains internal
1.122 + * state should, additionally, override the {@link #implFlush implFlush} and
1.123 + * {@link #implReset implReset} methods.
1.124 + *
1.125 + * <p> Instances of this class are not safe for use by multiple concurrent
1.126 + * threads. </p>
1.127 + *
1.128 + *
1.129 + * @author Mark Reinhold
1.130 + * @author JSR-51 Expert Group
1.131 + * @since 1.4
1.132 + *
1.133 + * @see ByteBuffer
1.134 + * @see CharBuffer
1.135 + * @see Charset
1.136 + * @see CharsetEncoder
1.137 + */
1.138 +
1.139 +public abstract class CharsetDecoder {
1.140 +
1.141 + private final Charset charset;
1.142 + private final float averageCharsPerByte;
1.143 + private final float maxCharsPerByte;
1.144 +
1.145 + private String replacement;
1.146 + private CodingErrorAction malformedInputAction
1.147 + = CodingErrorAction.REPORT;
1.148 + private CodingErrorAction unmappableCharacterAction
1.149 + = CodingErrorAction.REPORT;
1.150 +
1.151 + // Internal states
1.152 + //
1.153 + private static final int ST_RESET = 0;
1.154 + private static final int ST_CODING = 1;
1.155 + private static final int ST_END = 2;
1.156 + private static final int ST_FLUSHED = 3;
1.157 +
1.158 + private int state = ST_RESET;
1.159 +
1.160 + private static String stateNames[]
1.161 + = { "RESET", "CODING", "CODING_END", "FLUSHED" };
1.162 +
1.163 +
1.164 + /**
1.165 + * Initializes a new decoder. The new decoder will have the given
1.166 + * chars-per-byte and replacement values. </p>
1.167 + *
1.168 + * @param averageCharsPerByte
1.169 + * A positive float value indicating the expected number of
1.170 + * characters that will be produced for each input byte
1.171 + *
1.172 + * @param maxCharsPerByte
1.173 + * A positive float value indicating the maximum number of
1.174 + * characters that will be produced for each input byte
1.175 + *
1.176 + * @param replacement
1.177 + * The initial replacement; must not be <tt>null</tt>, must have
1.178 + * non-zero length, must not be longer than maxCharsPerByte,
1.179 + * and must be {@link #isLegalReplacement </code>legal<code>}
1.180 + *
1.181 + * @throws IllegalArgumentException
1.182 + * If the preconditions on the parameters do not hold
1.183 + */
1.184 + private
1.185 + CharsetDecoder(Charset cs,
1.186 + float averageCharsPerByte,
1.187 + float maxCharsPerByte,
1.188 + String replacement)
1.189 + {
1.190 + this.charset = cs;
1.191 + if (averageCharsPerByte <= 0.0f)
1.192 + throw new IllegalArgumentException("Non-positive "
1.193 + + "averageCharsPerByte");
1.194 + if (maxCharsPerByte <= 0.0f)
1.195 + throw new IllegalArgumentException("Non-positive "
1.196 + + "maxCharsPerByte");
1.197 + if (!Charset.atBugLevel("1.4")) {
1.198 + if (averageCharsPerByte > maxCharsPerByte)
1.199 + throw new IllegalArgumentException("averageCharsPerByte"
1.200 + + " exceeds "
1.201 + + "maxCharsPerByte");
1.202 + }
1.203 + this.replacement = replacement;
1.204 + this.averageCharsPerByte = averageCharsPerByte;
1.205 + this.maxCharsPerByte = maxCharsPerByte;
1.206 + replaceWith(replacement);
1.207 + }
1.208 +
1.209 + /**
1.210 + * Initializes a new decoder. The new decoder will have the given
1.211 + * chars-per-byte values and its replacement will be the
1.212 + * string <tt>"\uFFFD"</tt>. </p>
1.213 + *
1.214 + * @param averageCharsPerByte
1.215 + * A positive float value indicating the expected number of
1.216 + * characters that will be produced for each input byte
1.217 + *
1.218 + * @param maxCharsPerByte
1.219 + * A positive float value indicating the maximum number of
1.220 + * characters that will be produced for each input byte
1.221 + *
1.222 + * @throws IllegalArgumentException
1.223 + * If the preconditions on the parameters do not hold
1.224 + */
1.225 + protected CharsetDecoder(Charset cs,
1.226 + float averageCharsPerByte,
1.227 + float maxCharsPerByte)
1.228 + {
1.229 + this(cs,
1.230 + averageCharsPerByte, maxCharsPerByte,
1.231 + "\uFFFD");
1.232 + }
1.233 +
1.234 + /**
1.235 + * Returns the charset that created this decoder. </p>
1.236 + *
1.237 + * @return This decoder's charset
1.238 + */
1.239 + public final Charset charset() {
1.240 + return charset;
1.241 + }
1.242 +
1.243 + /**
1.244 + * Returns this decoder's replacement value. </p>
1.245 + *
1.246 + * @return This decoder's current replacement,
1.247 + * which is never <tt>null</tt> and is never empty
1.248 + */
1.249 + public final String replacement() {
1.250 + return replacement;
1.251 + }
1.252 +
1.253 + /**
1.254 + * Changes this decoder's replacement value.
1.255 + *
1.256 + * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
1.257 + * method, passing the new replacement, after checking that the new
1.258 + * replacement is acceptable. </p>
1.259 + *
1.260 + * @param newReplacement
1.261 + *
1.262 +
1.263 + * The new replacement; must not be <tt>null</tt>
1.264 + * and must have non-zero length
1.265 +
1.266 +
1.267 +
1.268 +
1.269 +
1.270 +
1.271 +
1.272 + *
1.273 + * @return This decoder
1.274 + *
1.275 + * @throws IllegalArgumentException
1.276 + * If the preconditions on the parameter do not hold
1.277 + */
1.278 + public final CharsetDecoder replaceWith(String newReplacement) {
1.279 + if (newReplacement == null)
1.280 + throw new IllegalArgumentException("Null replacement");
1.281 + int len = newReplacement.length();
1.282 + if (len == 0)
1.283 + throw new IllegalArgumentException("Empty replacement");
1.284 + if (len > maxCharsPerByte)
1.285 + throw new IllegalArgumentException("Replacement too long");
1.286 +
1.287 +
1.288 +
1.289 +
1.290 + this.replacement = newReplacement;
1.291 + implReplaceWith(newReplacement);
1.292 + return this;
1.293 + }
1.294 +
1.295 + /**
1.296 + * Reports a change to this decoder's replacement value.
1.297 + *
1.298 + * <p> The default implementation of this method does nothing. This method
1.299 + * should be overridden by decoders that require notification of changes to
1.300 + * the replacement. </p>
1.301 + *
1.302 + * @param newReplacement
1.303 + */
1.304 + protected void implReplaceWith(String newReplacement) {
1.305 + }
1.306 +
1.307 +
1.308 +
1.309 +
1.310 +
1.311 +
1.312 +
1.313 +
1.314 +
1.315 +
1.316 +
1.317 +
1.318 +
1.319 +
1.320 +
1.321 +
1.322 +
1.323 +
1.324 +
1.325 +
1.326 +
1.327 +
1.328 +
1.329 +
1.330 +
1.331 +
1.332 +
1.333 +
1.334 +
1.335 +
1.336 +
1.337 +
1.338 +
1.339 +
1.340 +
1.341 +
1.342 +
1.343 +
1.344 +
1.345 +
1.346 +
1.347 + /**
1.348 + * Returns this decoder's current action for malformed-input errors. </p>
1.349 + *
1.350 + * @return The current malformed-input action, which is never <tt>null</tt>
1.351 + */
1.352 + public CodingErrorAction malformedInputAction() {
1.353 + return malformedInputAction;
1.354 + }
1.355 +
1.356 + /**
1.357 + * Changes this decoder's action for malformed-input errors. </p>
1.358 + *
1.359 + * <p> This method invokes the {@link #implOnMalformedInput
1.360 + * implOnMalformedInput} method, passing the new action. </p>
1.361 + *
1.362 + * @param newAction The new action; must not be <tt>null</tt>
1.363 + *
1.364 + * @return This decoder
1.365 + *
1.366 + * @throws IllegalArgumentException
1.367 + * If the precondition on the parameter does not hold
1.368 + */
1.369 + public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) {
1.370 + if (newAction == null)
1.371 + throw new IllegalArgumentException("Null action");
1.372 + malformedInputAction = newAction;
1.373 + implOnMalformedInput(newAction);
1.374 + return this;
1.375 + }
1.376 +
1.377 + /**
1.378 + * Reports a change to this decoder's malformed-input action.
1.379 + *
1.380 + * <p> The default implementation of this method does nothing. This method
1.381 + * should be overridden by decoders that require notification of changes to
1.382 + * the malformed-input action. </p>
1.383 + */
1.384 + protected void implOnMalformedInput(CodingErrorAction newAction) { }
1.385 +
1.386 + /**
1.387 + * Returns this decoder's current action for unmappable-character errors.
1.388 + * </p>
1.389 + *
1.390 + * @return The current unmappable-character action, which is never
1.391 + * <tt>null</tt>
1.392 + */
1.393 + public CodingErrorAction unmappableCharacterAction() {
1.394 + return unmappableCharacterAction;
1.395 + }
1.396 +
1.397 + /**
1.398 + * Changes this decoder's action for unmappable-character errors.
1.399 + *
1.400 + * <p> This method invokes the {@link #implOnUnmappableCharacter
1.401 + * implOnUnmappableCharacter} method, passing the new action. </p>
1.402 + *
1.403 + * @param newAction The new action; must not be <tt>null</tt>
1.404 + *
1.405 + * @return This decoder
1.406 + *
1.407 + * @throws IllegalArgumentException
1.408 + * If the precondition on the parameter does not hold
1.409 + */
1.410 + public final CharsetDecoder onUnmappableCharacter(CodingErrorAction
1.411 + newAction)
1.412 + {
1.413 + if (newAction == null)
1.414 + throw new IllegalArgumentException("Null action");
1.415 + unmappableCharacterAction = newAction;
1.416 + implOnUnmappableCharacter(newAction);
1.417 + return this;
1.418 + }
1.419 +
1.420 + /**
1.421 + * Reports a change to this decoder's unmappable-character action.
1.422 + *
1.423 + * <p> The default implementation of this method does nothing. This method
1.424 + * should be overridden by decoders that require notification of changes to
1.425 + * the unmappable-character action. </p>
1.426 + */
1.427 + protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
1.428 +
1.429 + /**
1.430 + * Returns the average number of characters that will be produced for each
1.431 + * byte of input. This heuristic value may be used to estimate the size
1.432 + * of the output buffer required for a given input sequence. </p>
1.433 + *
1.434 + * @return The average number of characters produced
1.435 + * per byte of input
1.436 + */
1.437 + public final float averageCharsPerByte() {
1.438 + return averageCharsPerByte;
1.439 + }
1.440 +
1.441 + /**
1.442 + * Returns the maximum number of characters that will be produced for each
1.443 + * byte of input. This value may be used to compute the worst-case size
1.444 + * of the output buffer required for a given input sequence. </p>
1.445 + *
1.446 + * @return The maximum number of characters that will be produced per
1.447 + * byte of input
1.448 + */
1.449 + public final float maxCharsPerByte() {
1.450 + return maxCharsPerByte;
1.451 + }
1.452 +
1.453 + /**
1.454 + * Decodes as many bytes as possible from the given input buffer,
1.455 + * writing the results to the given output buffer.
1.456 + *
1.457 + * <p> The buffers are read from, and written to, starting at their current
1.458 + * positions. At most {@link Buffer#remaining in.remaining()} bytes
1.459 + * will be read and at most {@link Buffer#remaining out.remaining()}
1.460 + * characters will be written. The buffers' positions will be advanced to
1.461 + * reflect the bytes read and the characters written, but their marks and
1.462 + * limits will not be modified.
1.463 + *
1.464 + * <p> In addition to reading bytes from the input buffer and writing
1.465 + * characters to the output buffer, this method returns a {@link CoderResult}
1.466 + * object to describe its reason for termination:
1.467 + *
1.468 + * <ul>
1.469 + *
1.470 + * <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
1.471 + * input buffer as possible has been decoded. If there is no further
1.472 + * input then the invoker can proceed to the next step of the
1.473 + * <a href="#steps">decoding operation</a>. Otherwise this method
1.474 + * should be invoked again with further input. </p></li>
1.475 + *
1.476 + * <li><p> {@link CoderResult#OVERFLOW} indicates that there is
1.477 + * insufficient space in the output buffer to decode any more bytes.
1.478 + * This method should be invoked again with an output buffer that has
1.479 + * more {@linkplain Buffer#remaining remaining} characters. This is
1.480 + * typically done by draining any decoded characters from the output
1.481 + * buffer. </p></li>
1.482 + *
1.483 + * <li><p> A {@link CoderResult#malformedForLength
1.484 + * </code>malformed-input<code>} result indicates that a malformed-input
1.485 + * error has been detected. The malformed bytes begin at the input
1.486 + * buffer's (possibly incremented) position; the number of malformed
1.487 + * bytes may be determined by invoking the result object's {@link
1.488 + * CoderResult#length() length} method. This case applies only if the
1.489 + * {@link #onMalformedInput </code>malformed action<code>} of this decoder
1.490 + * is {@link CodingErrorAction#REPORT}; otherwise the malformed input
1.491 + * will be ignored or replaced, as requested. </p></li>
1.492 + *
1.493 + * <li><p> An {@link CoderResult#unmappableForLength
1.494 + * </code>unmappable-character<code>} result indicates that an
1.495 + * unmappable-character error has been detected. The bytes that
1.496 + * decode the unmappable character begin at the input buffer's (possibly
1.497 + * incremented) position; the number of such bytes may be determined
1.498 + * by invoking the result object's {@link CoderResult#length() length}
1.499 + * method. This case applies only if the {@link #onUnmappableCharacter
1.500 + * </code>unmappable action<code>} of this decoder is {@link
1.501 + * CodingErrorAction#REPORT}; otherwise the unmappable character will be
1.502 + * ignored or replaced, as requested. </p></li>
1.503 + *
1.504 + * </ul>
1.505 + *
1.506 + * In any case, if this method is to be reinvoked in the same decoding
1.507 + * operation then care should be taken to preserve any bytes remaining
1.508 + * in the input buffer so that they are available to the next invocation.
1.509 + *
1.510 + * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
1.511 + * the invoker can provide further input beyond that contained in the given
1.512 + * input buffer. If there is a possibility of providing additional input
1.513 + * then the invoker should pass <tt>false</tt> for this parameter; if there
1.514 + * is no possibility of providing further input then the invoker should
1.515 + * pass <tt>true</tt>. It is not erroneous, and in fact it is quite
1.516 + * common, to pass <tt>false</tt> in one invocation and later discover that
1.517 + * no further input was actually available. It is critical, however, that
1.518 + * the final invocation of this method in a sequence of invocations always
1.519 + * pass <tt>true</tt> so that any remaining undecoded input will be treated
1.520 + * as being malformed.
1.521 + *
1.522 + * <p> This method works by invoking the {@link #decodeLoop decodeLoop}
1.523 + * method, interpreting its results, handling error conditions, and
1.524 + * reinvoking it as necessary. </p>
1.525 + *
1.526 + *
1.527 + * @param in
1.528 + * The input byte buffer
1.529 + *
1.530 + * @param out
1.531 + * The output character buffer
1.532 + *
1.533 + * @param endOfInput
1.534 + * <tt>true</tt> if, and only if, the invoker can provide no
1.535 + * additional input bytes beyond those in the given buffer
1.536 + *
1.537 + * @return A coder-result object describing the reason for termination
1.538 + *
1.539 + * @throws IllegalStateException
1.540 + * If a decoding operation is already in progress and the previous
1.541 + * step was an invocation neither of the {@link #reset reset}
1.542 + * method, nor of this method with a value of <tt>false</tt> for
1.543 + * the <tt>endOfInput</tt> parameter, nor of this method with a
1.544 + * value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
1.545 + * but a return value indicating an incomplete decoding operation
1.546 + *
1.547 + * @throws CoderMalfunctionError
1.548 + * If an invocation of the decodeLoop method threw
1.549 + * an unexpected exception
1.550 + */
1.551 + public final CoderResult decode(ByteBuffer in, CharBuffer out,
1.552 + boolean endOfInput)
1.553 + {
1.554 + int newState = endOfInput ? ST_END : ST_CODING;
1.555 + if ((state != ST_RESET) && (state != ST_CODING)
1.556 + && !(endOfInput && (state == ST_END)))
1.557 + throwIllegalStateException(state, newState);
1.558 + state = newState;
1.559 +
1.560 + for (;;) {
1.561 +
1.562 + CoderResult cr;
1.563 + try {
1.564 + cr = decodeLoop(in, out);
1.565 + } catch (BufferUnderflowException x) {
1.566 + throw new CoderMalfunctionError(x);
1.567 + } catch (BufferOverflowException x) {
1.568 + throw new CoderMalfunctionError(x);
1.569 + }
1.570 +
1.571 + if (cr.isOverflow())
1.572 + return cr;
1.573 +
1.574 + if (cr.isUnderflow()) {
1.575 + if (endOfInput && in.hasRemaining()) {
1.576 + cr = CoderResult.malformedForLength(in.remaining());
1.577 + // Fall through to malformed-input case
1.578 + } else {
1.579 + return cr;
1.580 + }
1.581 + }
1.582 +
1.583 + CodingErrorAction action = null;
1.584 + if (cr.isMalformed())
1.585 + action = malformedInputAction;
1.586 + else if (cr.isUnmappable())
1.587 + action = unmappableCharacterAction;
1.588 + else
1.589 + assert false : cr.toString();
1.590 +
1.591 + if (action == CodingErrorAction.REPORT)
1.592 + return cr;
1.593 +
1.594 + if (action == CodingErrorAction.REPLACE) {
1.595 + if (out.remaining() < replacement.length())
1.596 + return CoderResult.OVERFLOW;
1.597 + out.put(replacement);
1.598 + }
1.599 +
1.600 + if ((action == CodingErrorAction.IGNORE)
1.601 + || (action == CodingErrorAction.REPLACE)) {
1.602 + // Skip erroneous input either way
1.603 + in.position(in.position() + cr.length());
1.604 + continue;
1.605 + }
1.606 +
1.607 + assert false;
1.608 + }
1.609 +
1.610 + }
1.611 +
1.612 + /**
1.613 + * Flushes this decoder.
1.614 + *
1.615 + * <p> Some decoders maintain internal state and may need to write some
1.616 + * final characters to the output buffer once the overall input sequence has
1.617 + * been read.
1.618 + *
1.619 + * <p> Any additional output is written to the output buffer beginning at
1.620 + * its current position. At most {@link Buffer#remaining out.remaining()}
1.621 + * characters will be written. The buffer's position will be advanced
1.622 + * appropriately, but its mark and limit will not be modified.
1.623 + *
1.624 + * <p> If this method completes successfully then it returns {@link
1.625 + * CoderResult#UNDERFLOW}. If there is insufficient room in the output
1.626 + * buffer then it returns {@link CoderResult#OVERFLOW}. If this happens
1.627 + * then this method must be invoked again, with an output buffer that has
1.628 + * more room, in order to complete the current <a href="#steps">decoding
1.629 + * operation</a>.
1.630 + *
1.631 + * <p> If this decoder has already been flushed then invoking this method
1.632 + * has no effect.
1.633 + *
1.634 + * <p> This method invokes the {@link #implFlush implFlush} method to
1.635 + * perform the actual flushing operation. </p>
1.636 + *
1.637 + * @param out
1.638 + * The output character buffer
1.639 + *
1.640 + * @return A coder-result object, either {@link CoderResult#UNDERFLOW} or
1.641 + * {@link CoderResult#OVERFLOW}
1.642 + *
1.643 + * @throws IllegalStateException
1.644 + * If the previous step of the current decoding operation was an
1.645 + * invocation neither of the {@link #flush flush} method nor of
1.646 + * the three-argument {@link
1.647 + * #decode(ByteBuffer,CharBuffer,boolean) decode} method
1.648 + * with a value of <tt>true</tt> for the <tt>endOfInput</tt>
1.649 + * parameter
1.650 + */
1.651 + public final CoderResult flush(CharBuffer out) {
1.652 + if (state == ST_END) {
1.653 + CoderResult cr = implFlush(out);
1.654 + if (cr.isUnderflow())
1.655 + state = ST_FLUSHED;
1.656 + return cr;
1.657 + }
1.658 +
1.659 + if (state != ST_FLUSHED)
1.660 + throwIllegalStateException(state, ST_FLUSHED);
1.661 +
1.662 + return CoderResult.UNDERFLOW; // Already flushed
1.663 + }
1.664 +
1.665 + /**
1.666 + * Flushes this decoder.
1.667 + *
1.668 + * <p> The default implementation of this method does nothing, and always
1.669 + * returns {@link CoderResult#UNDERFLOW}. This method should be overridden
1.670 + * by decoders that may need to write final characters to the output buffer
1.671 + * once the entire input sequence has been read. </p>
1.672 + *
1.673 + * @param out
1.674 + * The output character buffer
1.675 + *
1.676 + * @return A coder-result object, either {@link CoderResult#UNDERFLOW} or
1.677 + * {@link CoderResult#OVERFLOW}
1.678 + */
1.679 + protected CoderResult implFlush(CharBuffer out) {
1.680 + return CoderResult.UNDERFLOW;
1.681 + }
1.682 +
1.683 + /**
1.684 + * Resets this decoder, clearing any internal state.
1.685 + *
1.686 + * <p> This method resets charset-independent state and also invokes the
1.687 + * {@link #implReset() implReset} method in order to perform any
1.688 + * charset-specific reset actions. </p>
1.689 + *
1.690 + * @return This decoder
1.691 + *
1.692 + */
1.693 + public final CharsetDecoder reset() {
1.694 + implReset();
1.695 + state = ST_RESET;
1.696 + return this;
1.697 + }
1.698 +
1.699 + /**
1.700 + * Resets this decoder, clearing any charset-specific internal state.
1.701 + *
1.702 + * <p> The default implementation of this method does nothing. This method
1.703 + * should be overridden by decoders that maintain internal state. </p>
1.704 + */
1.705 + protected void implReset() { }
1.706 +
1.707 + /**
1.708 + * Decodes one or more bytes into one or more characters.
1.709 + *
1.710 + * <p> This method encapsulates the basic decoding loop, decoding as many
1.711 + * bytes as possible until it either runs out of input, runs out of room
1.712 + * in the output buffer, or encounters a decoding error. This method is
1.713 + * invoked by the {@link #decode decode} method, which handles result
1.714 + * interpretation and error recovery.
1.715 + *
1.716 + * <p> The buffers are read from, and written to, starting at their current
1.717 + * positions. At most {@link Buffer#remaining in.remaining()} bytes
1.718 + * will be read, and at most {@link Buffer#remaining out.remaining()}
1.719 + * characters will be written. The buffers' positions will be advanced to
1.720 + * reflect the bytes read and the characters written, but their marks and
1.721 + * limits will not be modified.
1.722 + *
1.723 + * <p> This method returns a {@link CoderResult} object to describe its
1.724 + * reason for termination, in the same manner as the {@link #decode decode}
1.725 + * method. Most implementations of this method will handle decoding errors
1.726 + * by returning an appropriate result object for interpretation by the
1.727 + * {@link #decode decode} method. An optimized implementation may instead
1.728 + * examine the relevant error action and implement that action itself.
1.729 + *
1.730 + * <p> An implementation of this method may perform arbitrary lookahead by
1.731 + * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
1.732 + * input. </p>
1.733 + *
1.734 + * @param in
1.735 + * The input byte buffer
1.736 + *
1.737 + * @param out
1.738 + * The output character buffer
1.739 + *
1.740 + * @return A coder-result object describing the reason for termination
1.741 + */
1.742 + protected abstract CoderResult decodeLoop(ByteBuffer in,
1.743 + CharBuffer out);
1.744 +
1.745 + /**
1.746 + * Convenience method that decodes the remaining content of a single input
1.747 + * byte buffer into a newly-allocated character buffer.
1.748 + *
1.749 + * <p> This method implements an entire <a href="#steps">decoding
1.750 + * operation</a>; that is, it resets this decoder, then it decodes the
1.751 + * bytes in the given byte buffer, and finally it flushes this
1.752 + * decoder. This method should therefore not be invoked if a decoding
1.753 + * operation is already in progress. </p>
1.754 + *
1.755 + * @param in
1.756 + * The input byte buffer
1.757 + *
1.758 + * @return A newly-allocated character buffer containing the result of the
1.759 + * decoding operation. The buffer's position will be zero and its
1.760 + * limit will follow the last character written.
1.761 + *
1.762 + * @throws IllegalStateException
1.763 + * If a decoding operation is already in progress
1.764 + *
1.765 + * @throws MalformedInputException
1.766 + * If the byte sequence starting at the input buffer's current
1.767 + * position is not legal for this charset and the current malformed-input action
1.768 + * is {@link CodingErrorAction#REPORT}
1.769 + *
1.770 + * @throws UnmappableCharacterException
1.771 + * If the byte sequence starting at the input buffer's current
1.772 + * position cannot be mapped to an equivalent character sequence and
1.773 + * the current unmappable-character action is {@link
1.774 + * CodingErrorAction#REPORT}
1.775 + */
1.776 + public final CharBuffer decode(ByteBuffer in)
1.777 + throws CharacterCodingException
1.778 + {
1.779 + int n = (int)(in.remaining() * averageCharsPerByte());
1.780 + CharBuffer out = CharBuffer.allocate(n);
1.781 +
1.782 + if ((n == 0) && (in.remaining() == 0))
1.783 + return out;
1.784 + reset();
1.785 + for (;;) {
1.786 + CoderResult cr = in.hasRemaining() ?
1.787 + decode(in, out, true) : CoderResult.UNDERFLOW;
1.788 + if (cr.isUnderflow())
1.789 + cr = flush(out);
1.790 +
1.791 + if (cr.isUnderflow())
1.792 + break;
1.793 + if (cr.isOverflow()) {
1.794 + n = 2*n + 1; // Ensure progress; n might be 0!
1.795 + CharBuffer o = CharBuffer.allocate(n);
1.796 + out.flip();
1.797 + o.put(out);
1.798 + out = o;
1.799 + continue;
1.800 + }
1.801 + cr.throwException();
1.802 + }
1.803 + out.flip();
1.804 + return out;
1.805 + }
1.806 +
1.807 +
1.808 +
1.809 + /**
1.810 + * Tells whether or not this decoder implements an auto-detecting charset.
1.811 + *
1.812 + * <p> The default implementation of this method always returns
1.813 + * <tt>false</tt>; it should be overridden by auto-detecting decoders to
1.814 + * return <tt>true</tt>. </p>
1.815 + *
1.816 + * @return <tt>true</tt> if, and only if, this decoder implements an
1.817 + * auto-detecting charset
1.818 + */
1.819 + public boolean isAutoDetecting() {
1.820 + return false;
1.821 + }
1.822 +
1.823 + /**
1.824 + * Tells whether or not this decoder has yet detected a
1.825 + * charset <i>(optional operation)</i>.
1.826 + *
1.827 + * <p> If this decoder implements an auto-detecting charset then at a
1.828 + * single point during a decoding operation this method may start returning
1.829 + * <tt>true</tt> to indicate that a specific charset has been detected in
1.830 + * the input byte sequence. Once this occurs, the {@link #detectedCharset
1.831 + * detectedCharset} method may be invoked to retrieve the detected charset.
1.832 + *
1.833 + * <p> That this method returns <tt>false</tt> does not imply that no bytes
1.834 + * have yet been decoded. Some auto-detecting decoders are capable of
1.835 + * decoding some, or even all, of an input byte sequence without fixing on
1.836 + * a particular charset.
1.837 + *
1.838 + * <p> The default implementation of this method always throws an {@link
1.839 + * UnsupportedOperationException}; it should be overridden by
1.840 + * auto-detecting decoders to return <tt>true</tt> once the input charset
1.841 + * has been determined. </p>
1.842 + *
1.843 + * @return <tt>true</tt> if, and only if, this decoder has detected a
1.844 + * specific charset
1.845 + *
1.846 + * @throws UnsupportedOperationException
1.847 + * If this decoder does not implement an auto-detecting charset
1.848 + */
1.849 + public boolean isCharsetDetected() {
1.850 + throw new UnsupportedOperationException();
1.851 + }
1.852 +
1.853 + /**
1.854 + * Retrieves the charset that was detected by this
1.855 + * decoder <i>(optional operation)</i>.
1.856 + *
1.857 + * <p> If this decoder implements an auto-detecting charset then this
1.858 + * method returns the actual charset once it has been detected. After that
1.859 + * point, this method returns the same value for the duration of the
1.860 + * current decoding operation. If not enough input bytes have yet been
1.861 + * read to determine the actual charset then this method throws an {@link
1.862 + * IllegalStateException}.
1.863 + *
1.864 + * <p> The default implementation of this method always throws an {@link
1.865 + * UnsupportedOperationException}; it should be overridden by
1.866 + * auto-detecting decoders to return the appropriate value. </p>
1.867 + *
1.868 + * @return The charset detected by this auto-detecting decoder,
1.869 + * or <tt>null</tt> if the charset has not yet been determined
1.870 + *
1.871 + * @throws IllegalStateException
1.872 + * If insufficient bytes have been read to determine a charset
1.873 + *
1.874 + * @throws UnsupportedOperationException
1.875 + * If this decoder does not implement an auto-detecting charset
1.876 + */
1.877 + public Charset detectedCharset() {
1.878 + throw new UnsupportedOperationException();
1.879 + }
1.880 +
1.881 +
1.882 +
1.883 +
1.884 +
1.885 +
1.886 +
1.887 +
1.888 +
1.889 +
1.890 +
1.891 +
1.892 +
1.893 +
1.894 +
1.895 +
1.896 +
1.897 +
1.898 +
1.899 +
1.900 +
1.901 +
1.902 +
1.903 +
1.904 +
1.905 +
1.906 +
1.907 +
1.908 +
1.909 +
1.910 +
1.911 +
1.912 +
1.913 +
1.914 +
1.915 +
1.916 +
1.917 +
1.918 +
1.919 +
1.920 +
1.921 +
1.922 +
1.923 +
1.924 +
1.925 +
1.926 +
1.927 +
1.928 +
1.929 +
1.930 +
1.931 +
1.932 +
1.933 +
1.934 +
1.935 +
1.936 +
1.937 +
1.938 +
1.939 +
1.940 +
1.941 +
1.942 +
1.943 +
1.944 +
1.945 +
1.946 +
1.947 +
1.948 +
1.949 +
1.950 +
1.951 +
1.952 +
1.953 +
1.954 +
1.955 +
1.956 +
1.957 +
1.958 +
1.959 +
1.960 +
1.961 +
1.962 +
1.963 +
1.964 +
1.965 +
1.966 +
1.967 +
1.968 +
1.969 +
1.970 + private void throwIllegalStateException(int from, int to) {
1.971 + throw new IllegalStateException("Current state = " + stateNames[from]
1.972 + + ", new state = " + stateNames[to]);
1.973 + }
1.974 +
1.975 +}