The input $itype$ sequence is provided in a $itype$ buffer or a series * of such buffers. The output $otype$ sequence is written to a $otype$ buffer * or a series of such buffers. $A$ $coder$ should always be used by making * the following sequence of method invocations, hereinafter referred to as $a$ * $coding$ operation: * *
Reset the $coder$ via the {@link #reset reset} method, unless it * has not been used before;
Invoke the {@link #$code$ $code$} method zero or more times, as * long as additional input may be available, passing false for the * endOfInput argument and filling the input buffer and flushing the * output buffer between invocations;
Invoke the {@link #$code$ $code$} method one final time, passing * true for the endOfInput argument; and then
Invoke the {@link #flush flush} method so that the $coder$ can * flush any internal state to the output buffer.
There are two general types of $coding$ errors. If the input $itype$
* sequence is $notLegal$ then the input is considered malformed. If
* the input $itype$ sequence is legal but cannot be mapped to a valid
* $outSequence$ then an unmappable character has been encountered.
*
*
*
* How $a$ $coding$ error is handled depends upon the action requested for
* that type of error, which is described by an instance of the {@link
* CodingErrorAction} class. The possible error actions are to {@link
* CodingErrorAction#IGNORE ignore The default action for malformed-input and unmappable-character errors
* is to {@link CodingErrorAction#REPORT This class is designed to handle many of the details of the $coding$
* process, including the implementation of error actions. $A$ $coder$ for a
* specific charset, which is a concrete subclass of this class, need only
* implement the abstract {@link #$code$Loop $code$Loop} method, which
* encapsulates the basic $coding$ loop. A subclass that maintains internal
* state should, additionally, override the {@link #implFlush implFlush} and
* {@link #implReset implReset} methods.
*
* Instances of this class are not safe for use by multiple concurrent
* threads. This method invokes the {@link #implReplaceWith implReplaceWith}
* method, passing the new replacement, after checking that the new
* replacement is acceptable. The default implementation of this method does nothing. This method
* should be overridden by $coder$s that require notification of changes to
* the replacement. A replacement is legal if, and only if, it is a legal sequence of
* bytes in this encoder's charset; that is, it must be possible to decode
* the replacement into one or more sixteen-bit Unicode characters.
*
* The default implementation of this method is not very efficient; it
* should generally be overridden to improve performance. This method invokes the {@link #implOnMalformedInput
* implOnMalformedInput} method, passing the new action. The default implementation of this method does nothing. This method
* should be overridden by $coder$s that require notification of changes to
* the malformed-input action. This method invokes the {@link #implOnUnmappableCharacter
* implOnUnmappableCharacter} method, passing the new action. The default implementation of this method does nothing. This method
* should be overridden by $coder$s that require notification of changes to
* the unmappable-character action. The buffers are read from, and written to, starting at their current
* positions. At most {@link Buffer#remaining in.remaining()} $itype$s
* will be read and at most {@link Buffer#remaining out.remaining()}
* $otype$s will be written. The buffers' positions will be advanced to
* reflect the $itype$s read and the $otype$s written, but their marks and
* limits will not be modified.
*
* In addition to reading $itype$s from the input buffer and writing
* $otype$s to the output buffer, this method returns a {@link CoderResult}
* object to describe its reason for termination:
*
* {@link CoderResult#UNDERFLOW} indicates that as much of the
* input buffer as possible has been $code$d. If there is no further
* input then the invoker can proceed to the next step of the
* $coding$ operation. Otherwise this method
* should be invoked again with further input. {@link CoderResult#OVERFLOW} indicates that there is
* insufficient space in the output buffer to $code$ any more $itype$s.
* This method should be invoked again with an output buffer that has
* more {@linkplain Buffer#remaining remaining} $otype$s. This is
* typically done by draining any $code$d $otype$s from the output
* buffer. A {@link CoderResult#malformedForLength
* An {@link CoderResult#unmappableForLength
* unmappable-character The endOfInput parameter advises this method as to whether
* the invoker can provide further input beyond that contained in the given
* input buffer. If there is a possibility of providing additional input
* then the invoker should pass false for this parameter; if there
* is no possibility of providing further input then the invoker should
* pass true. It is not erroneous, and in fact it is quite
* common, to pass false in one invocation and later discover that
* no further input was actually available. It is critical, however, that
* the final invocation of this method in a sequence of invocations always
* pass true so that any remaining un$code$d input will be treated
* as being malformed.
*
* This method works by invoking the {@link #$code$Loop $code$Loop}
* method, interpreting its results, handling error conditions, and
* reinvoking it as necessary. Some $coder$s maintain internal state and may need to write some
* final $otype$s to the output buffer once the overall input sequence has
* been read.
*
* Any additional output is written to the output buffer beginning at
* its current position. At most {@link Buffer#remaining out.remaining()}
* $otype$s will be written. The buffer's position will be advanced
* appropriately, but its mark and limit will not be modified.
*
* If this method completes successfully then it returns {@link
* CoderResult#UNDERFLOW}. If there is insufficient room in the output
* buffer then it returns {@link CoderResult#OVERFLOW}. If this happens
* then this method must be invoked again, with an output buffer that has
* more room, in order to complete the current $coding$
* operation.
*
* If this $coder$ has already been flushed then invoking this method
* has no effect.
*
* This method invokes the {@link #implFlush implFlush} method to
* perform the actual flushing operation. The default implementation of this method does nothing, and always
* returns {@link CoderResult#UNDERFLOW}. This method should be overridden
* by $coder$s that may need to write final $otype$s to the output buffer
* once the entire input sequence has been read. This method resets charset-independent state and also invokes the
* {@link #implReset() implReset} method in order to perform any
* charset-specific reset actions. The default implementation of this method does nothing. This method
* should be overridden by $coder$s that maintain internal state. This method encapsulates the basic $coding$ loop, $coding$ as many
* $itype$s as possible until it either runs out of input, runs out of room
* in the output buffer, or encounters $a$ $coding$ error. This method is
* invoked by the {@link #$code$ $code$} method, which handles result
* interpretation and error recovery.
*
* The buffers are read from, and written to, starting at their current
* positions. At most {@link Buffer#remaining in.remaining()} $itype$s
* will be read, and at most {@link Buffer#remaining out.remaining()}
* $otype$s will be written. The buffers' positions will be advanced to
* reflect the $itype$s read and the $otype$s written, but their marks and
* limits will not be modified.
*
* This method returns a {@link CoderResult} object to describe its
* reason for termination, in the same manner as the {@link #$code$ $code$}
* method. Most implementations of this method will handle $coding$ errors
* by returning an appropriate result object for interpretation by the
* {@link #$code$ $code$} method. An optimized implementation may instead
* examine the relevant error action and implement that action itself.
*
* An implementation of this method may perform arbitrary lookahead by
* returning {@link CoderResult#UNDERFLOW} until it receives sufficient
* input. This method implements an entire $coding$
* operation; that is, it resets this $coder$, then it $code$s the
* $itype$s in the given $itype$ buffer, and finally it flushes this
* $coder$. This method should therefore not be invoked if $a$ $coding$
* operation is already in progress. The default implementation of this method always returns
* false; it should be overridden by auto-detecting decoders to
* return true. If this decoder implements an auto-detecting charset then at a
* single point during a decoding operation this method may start returning
* true to indicate that a specific charset has been detected in
* the input byte sequence. Once this occurs, the {@link #detectedCharset
* detectedCharset} method may be invoked to retrieve the detected charset.
*
* That this method returns false does not imply that no bytes
* have yet been decoded. Some auto-detecting decoders are capable of
* decoding some, or even all, of an input byte sequence without fixing on
* a particular charset.
*
* The default implementation of this method always throws an {@link
* UnsupportedOperationException}; it should be overridden by
* auto-detecting decoders to return true once the input charset
* has been determined. If this decoder implements an auto-detecting charset then this
* method returns the actual charset once it has been detected. After that
* point, this method returns the same value for the duration of the
* current decoding operation. If not enough input bytes have yet been
* read to determine the actual charset then this method throws an {@link
* IllegalStateException}.
*
* The default implementation of this method always throws an {@link
* UnsupportedOperationException}; it should be overridden by
* auto-detecting decoders to return the appropriate value. This method returns false if the given character is a
* surrogate character; such characters can be interpreted only when they
* are members of a pair consisting of a high surrogate followed by a low
* surrogate. The {@link #canEncode(java.lang.CharSequence)
* canEncode(CharSequence)} method may be used to test whether or not a
* character sequence can be encoded.
*
* This method may modify this encoder's state; it should therefore not
* be invoked if an encoding operation is already in
* progress.
*
* The default implementation of this method is not very efficient; it
* should generally be overridden to improve performance. If this method returns false for a particular character
* sequence then more information about why the sequence cannot be encoded
* may be obtained by performing a full encoding
* operation.
*
* This method may modify this encoder's state; it should therefore not
* be invoked if an encoding operation is already in progress.
*
* The default implementation of this method is not very efficient; it
* should generally be overridden to improve performance. } the erroneous input, {@link
* CodingErrorAction#REPORT report} the error to the invoker via
* the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
* replace} the erroneous input with the current value of the
* replacement $replTypeName$. The replacement
*
#if[encoder]
* is initially set to the $coder$'s default replacement, which often
* (but not always) has the initial value $defaultReplName$;
#end[encoder]
#if[decoder]
* has the initial value $defaultReplName$;
#end[decoder]
*
* its value may be changed via the {@link #replaceWith($replFQType$)
* replaceWith} method.
*
* report} them. The
* malformed-input error action may be changed via the {@link
* #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
* unmappable-character action may be changed via the {@link
* #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
*
* legal}
*
* @throws IllegalArgumentException
* If the preconditions on the parameters do not hold
*/
{#if[encoder]?protected:private}
Charset$Coder$(Charset cs,
float average$ItypesPerOtype$,
float max$ItypesPerOtype$,
$replType$ replacement)
{
this.charset = cs;
if (average$ItypesPerOtype$ <= 0.0f)
throw new IllegalArgumentException("Non-positive "
+ "average$ItypesPerOtype$");
if (max$ItypesPerOtype$ <= 0.0f)
throw new IllegalArgumentException("Non-positive "
+ "max$ItypesPerOtype$");
if (!Charset.atBugLevel("1.4")) {
if (average$ItypesPerOtype$ > max$ItypesPerOtype$)
throw new IllegalArgumentException("average$ItypesPerOtype$"
+ " exceeds "
+ "max$ItypesPerOtype$");
}
this.replacement = replacement;
this.average$ItypesPerOtype$ = average$ItypesPerOtype$;
this.max$ItypesPerOtype$ = max$ItypesPerOtype$;
replaceWith(replacement);
}
/**
* Initializes a new $coder$. The new $coder$ will have the given
* $otypes-per-itype$ values and its replacement will be the
* $replTypeName$ $defaultReplName$.
*
* @param average$ItypesPerOtype$
* A positive float value indicating the expected number of
* $otype$s that will be produced for each input $itype$
*
* @param max$ItypesPerOtype$
* A positive float value indicating the maximum number of
* $otype$s that will be produced for each input $itype$
*
* @throws IllegalArgumentException
* If the preconditions on the parameters do not hold
*/
protected Charset$Coder$(Charset cs,
float average$ItypesPerOtype$,
float max$ItypesPerOtype$)
{
this(cs,
average$ItypesPerOtype$, max$ItypesPerOtype$,
$defaultRepl$);
}
/**
* Returns the charset that created this $coder$.
*
* @return This $coder$'s charset
*/
public final Charset charset() {
return charset;
}
/**
* Returns this $coder$'s replacement value.
*
* @return This $coder$'s current replacement,
* which is never null and is never empty
*/
public final $replType$ replacement() {
#if[decoder]
return replacement;
#end[decoder]
#if[encoder]
return Arrays.copyOf(replacement, replacement.$replLength$);
#end[encoder]
}
/**
* Changes this $coder$'s replacement value.
*
* legal}
#end[encoder]
*
* @return This $coder$
*
* @throws IllegalArgumentException
* If the preconditions on the parameter do not hold
*/
public final Charset$Coder$ replaceWith($replType$ newReplacement) {
if (newReplacement == null)
throw new IllegalArgumentException("Null replacement");
int len = newReplacement.$replLength$;
if (len == 0)
throw new IllegalArgumentException("Empty replacement");
if (len > max$ItypesPerOtype$)
throw new IllegalArgumentException("Replacement too long");
#if[decoder]
this.replacement = newReplacement;
#end[decoder]
#if[encoder]
if (!isLegalReplacement(newReplacement))
throw new IllegalArgumentException("Illegal replacement");
this.replacement = Arrays.copyOf(newReplacement, newReplacement.$replLength$);
#end[encoder]
implReplaceWith(this.replacement);
return this;
}
/**
* Reports a change to this $coder$'s replacement value.
*
* malformed-input
*
*
} result indicates that a malformed-input
* error has been detected. The malformed $itype$s begin at the input
* buffer's (possibly incremented) position; the number of malformed
* $itype$s may be determined by invoking the result object's {@link
* CoderResult#length() length} method. This case applies only if the
* {@link #onMalformedInput malformed action} of this $coder$
* is {@link CodingErrorAction#REPORT}; otherwise the malformed input
* will be ignored or replaced, as requested. } result indicates that an
* unmappable-character error has been detected. The $itype$s that
* $code$ the unmappable character begin at the input buffer's (possibly
* incremented) position; the number of such $itype$s may be determined
* by invoking the result object's {@link CoderResult#length() length}
* method. This case applies only if the {@link #onUnmappableCharacter
* unmappable action} of this $coder$ is {@link
* CodingErrorAction#REPORT}; otherwise the unmappable character will be
* ignored or replaced, as requested.