~ubuntu-branches/ubuntu/precise/openjdk-7/precise-security

« back to all changes in this revision

Viewing changes to generated/java/nio/charset/CharsetEncoder.java

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2012-04-11 07:21:41 UTC
  • mfrom: (1.3.8) (8.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20120411072141-v8i0x0ejg8sf7i5p
Tags: 7~u3-2.1.1~pre1-1ubuntu1
Regenerate the control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2000-2006 Sun Microsystems, Inc.  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.  Sun designates this
 
8
 * particular file as subject to the "Classpath" exception as provided
 
9
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 
22
 * CA 95054 USA or visit www.sun.com if you need additional information or
 
23
 * have any questions.
 
24
 */
 
25
 
 
26
// -- This file was mechanically generated: Do not edit! -- //
 
27
 
 
28
package java.nio.charset;
 
29
 
 
30
import java.nio.Buffer;
 
31
import java.nio.ByteBuffer;
 
32
import java.nio.CharBuffer;
 
33
import java.nio.BufferOverflowException;
 
34
import java.nio.BufferUnderflowException;
 
35
import java.lang.ref.WeakReference;
 
36
import java.nio.charset.CoderMalfunctionError;                  // javadoc
 
37
 
 
38
 
 
39
/**
 
40
 * An engine that can transform a sequence of sixteen-bit Unicode characters into a sequence of
 
41
 * bytes in a specific charset.
 
42
 *
 
43
 * <a name="steps">
 
44
 *
 
45
 * <p> The input character sequence is provided in a character buffer or a series
 
46
 * of such buffers.  The output byte sequence is written to a byte buffer
 
47
 * or a series of such buffers.  An encoder should always be used by making
 
48
 * the following sequence of method invocations, hereinafter referred to as an
 
49
 * <i>encoding operation</i>:
 
50
 *
 
51
 * <ol>
 
52
 *
 
53
 *   <li><p> Reset the encoder via the {@link #reset reset} method, unless it
 
54
 *   has not been used before; </p></li>
 
55
 *
 
56
 *   <li><p> Invoke the {@link #encode encode} method zero or more times, as
 
57
 *   long as additional input may be available, passing <tt>false</tt> for the
 
58
 *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
 
59
 *   output buffer between invocations; </p></li>
 
60
 *
 
61
 *   <li><p> Invoke the {@link #encode encode} method one final time, passing
 
62
 *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
 
63
 *
 
64
 *   <li><p> Invoke the {@link #flush flush} method so that the encoder can
 
65
 *   flush any internal state to the output buffer. </p></li>
 
66
 *
 
67
 * </ol>
 
68
 *
 
69
 * Each invocation of the {@link #encode encode} method will encode as many
 
70
 * characters as possible from the input buffer, writing the resulting bytes
 
71
 * to the output buffer.  The {@link #encode encode} method returns when more
 
72
 * input is required, when there is not enough room in the output buffer, or
 
73
 * when an encoding error has occurred.  In each case a {@link CoderResult}
 
74
 * object is returned to describe the reason for termination.  An invoker can
 
75
 * examine this object and fill the input buffer, flush the output buffer, or
 
76
 * attempt to recover from an encoding error, as appropriate, and try again.
 
77
 *
 
78
 * <a name="ce">
 
79
 *
 
80
 * <p> There are two general types of encoding errors.  If the input character
 
81
 * sequence is not a legal sixteen-bit Unicode sequence then the input is considered <i>malformed</i>.  If
 
82
 * the input character sequence is legal but cannot be mapped to a valid
 
83
 * byte sequence in the given charset then an <i>unmappable character</i> has been encountered.
 
84
 *
 
85
 * <a name="cae">
 
86
 *
 
87
 * <p> How an encoding error is handled depends upon the action requested for
 
88
 * that type of error, which is described by an instance of the {@link
 
89
 * CodingErrorAction} class.  The possible error actions are to {@link
 
90
 * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
 
91
 * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
 
92
 * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
 
93
 * </code>replace<code>} the erroneous input with the current value of the
 
94
 * replacement byte array.  The replacement
 
95
 *
 
96
 
 
97
 * is initially set to the encoder's default replacement, which often
 
98
 * (but not always) has the initial value&nbsp;<tt>{</tt>&nbsp;<tt>(byte)'?'</tt>&nbsp;<tt>}</tt>;
 
99
 
 
100
 
 
101
 
 
102
 
 
103
 *
 
104
 * its value may be changed via the {@link #replaceWith(byte[])
 
105
 * replaceWith} method.
 
106
 *
 
107
 * <p> The default action for malformed-input and unmappable-character errors
 
108
 * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
 
109
 * malformed-input error action may be changed via the {@link
 
110
 * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
 
111
 * unmappable-character action may be changed via the {@link
 
112
 * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
 
113
 *
 
114
 * <p> This class is designed to handle many of the details of the encoding
 
115
 * process, including the implementation of error actions.  An encoder for a
 
116
 * specific charset, which is a concrete subclass of this class, need only
 
117
 * implement the abstract {@link #encodeLoop encodeLoop} method, which
 
118
 * encapsulates the basic encoding loop.  A subclass that maintains internal
 
119
 * state should, additionally, override the {@link #implFlush implFlush} and
 
120
 * {@link #implReset implReset} methods.
 
121
 *
 
122
 * <p> Instances of this class are not safe for use by multiple concurrent
 
123
 * threads.  </p>
 
124
 *
 
125
 *
 
126
 * @author Mark Reinhold
 
127
 * @author JSR-51 Expert Group
 
128
 * @since 1.4
 
129
 *
 
130
 * @see ByteBuffer
 
131
 * @see CharBuffer
 
132
 * @see Charset
 
133
 * @see CharsetDecoder
 
134
 */
 
135
 
 
136
public abstract class CharsetEncoder {
 
137
 
 
138
    private final Charset charset;
 
139
    private final float averageBytesPerChar;
 
140
    private final float maxBytesPerChar;
 
141
 
 
142
    private byte[] replacement;
 
143
    private CodingErrorAction malformedInputAction
 
144
        = CodingErrorAction.REPORT;
 
145
    private CodingErrorAction unmappableCharacterAction
 
146
        = CodingErrorAction.REPORT;
 
147
 
 
148
    // Internal states
 
149
    //
 
150
    private static final int ST_RESET   = 0;
 
151
    private static final int ST_CODING  = 1;
 
152
    private static final int ST_END     = 2;
 
153
    private static final int ST_FLUSHED = 3;
 
154
 
 
155
    private int state = ST_RESET;
 
156
 
 
157
    private static String stateNames[]
 
158
        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
 
159
 
 
160
 
 
161
    /**
 
162
     * Initializes a new encoder.  The new encoder will have the given
 
163
     * bytes-per-char and replacement values. </p>
 
164
     *
 
165
     * @param  averageBytesPerChar
 
166
     *         A positive float value indicating the expected number of
 
167
     *         bytes that will be produced for each input character
 
168
     *
 
169
     * @param  maxBytesPerChar
 
170
     *         A positive float value indicating the maximum number of
 
171
     *         bytes that will be produced for each input character
 
172
     *
 
173
     * @param  replacement
 
174
     *         The initial replacement; must not be <tt>null</tt>, must have
 
175
     *         non-zero length, must not be longer than maxBytesPerChar,
 
176
     *         and must be {@link #isLegalReplacement </code>legal<code>}
 
177
     *
 
178
     * @throws  IllegalArgumentException
 
179
     *          If the preconditions on the parameters do not hold
 
180
     */
 
181
    protected
 
182
    CharsetEncoder(Charset cs,
 
183
                   float averageBytesPerChar,
 
184
                   float maxBytesPerChar,
 
185
                   byte[] replacement)
 
186
    {
 
187
        this.charset = cs;
 
188
        if (averageBytesPerChar <= 0.0f)
 
189
            throw new IllegalArgumentException("Non-positive "
 
190
                                               + "averageBytesPerChar");
 
191
        if (maxBytesPerChar <= 0.0f)
 
192
            throw new IllegalArgumentException("Non-positive "
 
193
                                               + "maxBytesPerChar");
 
194
        if (!Charset.atBugLevel("1.4")) {
 
195
            if (averageBytesPerChar > maxBytesPerChar)
 
196
                throw new IllegalArgumentException("averageBytesPerChar"
 
197
                                                   + " exceeds "
 
198
                                                   + "maxBytesPerChar");
 
199
        }
 
200
        this.replacement = replacement;
 
201
        this.averageBytesPerChar = averageBytesPerChar;
 
202
        this.maxBytesPerChar = maxBytesPerChar;
 
203
        replaceWith(replacement);
 
204
    }
 
205
 
 
206
    /**
 
207
     * Initializes a new encoder.  The new encoder will have the given
 
208
     * bytes-per-char values and its replacement will be the
 
209
     * byte array <tt>{</tt>&nbsp;<tt>(byte)'?'</tt>&nbsp;<tt>}</tt>. </p>
 
210
     *
 
211
     * @param  averageBytesPerChar
 
212
     *         A positive float value indicating the expected number of
 
213
     *         bytes that will be produced for each input character
 
214
     *
 
215
     * @param  maxBytesPerChar
 
216
     *         A positive float value indicating the maximum number of
 
217
     *         bytes that will be produced for each input character
 
218
     *
 
219
     * @throws  IllegalArgumentException
 
220
     *          If the preconditions on the parameters do not hold
 
221
     */
 
222
    protected CharsetEncoder(Charset cs,
 
223
                             float averageBytesPerChar,
 
224
                             float maxBytesPerChar)
 
225
    {
 
226
        this(cs,
 
227
             averageBytesPerChar, maxBytesPerChar,
 
228
             new byte[] { (byte)'?' });
 
229
    }
 
230
 
 
231
    /**
 
232
     * Returns the charset that created this encoder.  </p>
 
233
     *
 
234
     * @return  This encoder's charset
 
235
     */
 
236
    public final Charset charset() {
 
237
        return charset;
 
238
    }
 
239
 
 
240
    /**
 
241
     * Returns this encoder's replacement value. </p>
 
242
     *
 
243
     * @return  This encoder's current replacement,
 
244
     *          which is never <tt>null</tt> and is never empty
 
245
     */
 
246
    public final byte[] replacement() {
 
247
        return replacement;
 
248
    }
 
249
 
 
250
    /**
 
251
     * Changes this encoder's replacement value.
 
252
     *
 
253
     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
 
254
     * method, passing the new replacement, after checking that the new
 
255
     * replacement is acceptable.  </p>
 
256
     *
 
257
     * @param  newReplacement
 
258
     *
 
259
 
 
260
 
 
261
 
 
262
 
 
263
 
 
264
     *         The new replacement; must not be <tt>null</tt>, must have
 
265
     *         non-zero length, must not be longer than the value returned by
 
266
     *         the {@link #maxBytesPerChar() maxBytesPerChar} method, and
 
267
     *         must be {@link #isLegalReplacement </code>legal<code>}
 
268
 
 
269
     *
 
270
     * @return  This encoder
 
271
     *
 
272
     * @throws  IllegalArgumentException
 
273
     *          If the preconditions on the parameter do not hold
 
274
     */
 
275
    public final CharsetEncoder replaceWith(byte[] newReplacement) {
 
276
        if (newReplacement == null)
 
277
            throw new IllegalArgumentException("Null replacement");
 
278
        int len = newReplacement.length;
 
279
        if (len == 0)
 
280
            throw new IllegalArgumentException("Empty replacement");
 
281
        if (len > maxBytesPerChar)
 
282
            throw new IllegalArgumentException("Replacement too long");
 
283
 
 
284
        if (!isLegalReplacement(newReplacement))
 
285
            throw new IllegalArgumentException("Illegal replacement");
 
286
 
 
287
        this.replacement = newReplacement;
 
288
        implReplaceWith(newReplacement);
 
289
        return this;
 
290
    }
 
291
 
 
292
    /**
 
293
     * Reports a change to this encoder's replacement value.
 
294
     *
 
295
     * <p> The default implementation of this method does nothing.  This method
 
296
     * should be overridden by encoders that require notification of changes to
 
297
     * the replacement.  </p>
 
298
     *
 
299
     * @param  newReplacement
 
300
     */
 
301
    protected void implReplaceWith(byte[] newReplacement) {
 
302
    }
 
303
 
 
304
 
 
305
 
 
306
    private WeakReference<CharsetDecoder> cachedDecoder = null;
 
307
 
 
308
    /**
 
309
     * Tells whether or not the given byte array is a legal replacement value
 
310
     * for this encoder.
 
311
     *
 
312
     * <p> A replacement is legal if, and only if, it is a legal sequence of
 
313
     * bytes in this encoder's charset; that is, it must be possible to decode
 
314
     * the replacement into one or more sixteen-bit Unicode characters.
 
315
     *
 
316
     * <p> The default implementation of this method is not very efficient; it
 
317
     * should generally be overridden to improve performance.  </p>
 
318
     *
 
319
     * @param  repl  The byte array to be tested
 
320
     *
 
321
     * @return  <tt>true</tt> if, and only if, the given byte array
 
322
     *          is a legal replacement value for this encoder
 
323
     */
 
324
    public boolean isLegalReplacement(byte[] repl) {
 
325
        WeakReference<CharsetDecoder> wr = cachedDecoder;
 
326
        CharsetDecoder dec = null;
 
327
        if ((wr == null) || ((dec = wr.get()) == null)) {
 
328
            dec = charset().newDecoder();
 
329
            dec.onMalformedInput(CodingErrorAction.REPORT);
 
330
            dec.onUnmappableCharacter(CodingErrorAction.REPORT);
 
331
            cachedDecoder = new WeakReference<CharsetDecoder>(dec);
 
332
        } else {
 
333
            dec.reset();
 
334
        }
 
335
        ByteBuffer bb = ByteBuffer.wrap(repl);
 
336
        CharBuffer cb = CharBuffer.allocate((int)(bb.remaining()
 
337
                                                  * dec.maxCharsPerByte()));
 
338
        CoderResult cr = dec.decode(bb, cb, true);
 
339
        return !cr.isError();
 
340
    }
 
341
 
 
342
 
 
343
 
 
344
    /**
 
345
     * Returns this encoder's current action for malformed-input errors.  </p>
 
346
     *
 
347
     * @return The current malformed-input action, which is never <tt>null</tt>
 
348
     */
 
349
    public CodingErrorAction malformedInputAction() {
 
350
        return malformedInputAction;
 
351
    }
 
352
 
 
353
    /**
 
354
     * Changes this encoder's action for malformed-input errors.  </p>
 
355
     *
 
356
     * <p> This method invokes the {@link #implOnMalformedInput
 
357
     * implOnMalformedInput} method, passing the new action.  </p>
 
358
     *
 
359
     * @param  newAction  The new action; must not be <tt>null</tt>
 
360
     *
 
361
     * @return  This encoder
 
362
     *
 
363
     * @throws IllegalArgumentException
 
364
     *         If the precondition on the parameter does not hold
 
365
     */
 
366
    public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) {
 
367
        if (newAction == null)
 
368
            throw new IllegalArgumentException("Null action");
 
369
        malformedInputAction = newAction;
 
370
        implOnMalformedInput(newAction);
 
371
        return this;
 
372
    }
 
373
 
 
374
    /**
 
375
     * Reports a change to this encoder's malformed-input action.
 
376
     *
 
377
     * <p> The default implementation of this method does nothing.  This method
 
378
     * should be overridden by encoders that require notification of changes to
 
379
     * the malformed-input action.  </p>
 
380
     */
 
381
    protected void implOnMalformedInput(CodingErrorAction newAction) { }
 
382
 
 
383
    /**
 
384
     * Returns this encoder's current action for unmappable-character errors.
 
385
     * </p>
 
386
     *
 
387
     * @return The current unmappable-character action, which is never
 
388
     *         <tt>null</tt>
 
389
     */
 
390
    public CodingErrorAction unmappableCharacterAction() {
 
391
        return unmappableCharacterAction;
 
392
    }
 
393
 
 
394
    /**
 
395
     * Changes this encoder's action for unmappable-character errors.
 
396
     *
 
397
     * <p> This method invokes the {@link #implOnUnmappableCharacter
 
398
     * implOnUnmappableCharacter} method, passing the new action.  </p>
 
399
     *
 
400
     * @param  newAction  The new action; must not be <tt>null</tt>
 
401
     *
 
402
     * @return  This encoder
 
403
     *
 
404
     * @throws IllegalArgumentException
 
405
     *         If the precondition on the parameter does not hold
 
406
     */
 
407
    public final CharsetEncoder onUnmappableCharacter(CodingErrorAction
 
408
                                                      newAction)
 
409
    {
 
410
        if (newAction == null)
 
411
            throw new IllegalArgumentException("Null action");
 
412
        unmappableCharacterAction = newAction;
 
413
        implOnUnmappableCharacter(newAction);
 
414
        return this;
 
415
    }
 
416
 
 
417
    /**
 
418
     * Reports a change to this encoder's unmappable-character action.
 
419
     *
 
420
     * <p> The default implementation of this method does nothing.  This method
 
421
     * should be overridden by encoders that require notification of changes to
 
422
     * the unmappable-character action.  </p>
 
423
     */
 
424
    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
 
425
 
 
426
    /**
 
427
     * Returns the average number of bytes that will be produced for each
 
428
     * character of input.  This heuristic value may be used to estimate the size
 
429
     * of the output buffer required for a given input sequence. </p>
 
430
     *
 
431
     * @return  The average number of bytes produced
 
432
     *          per character of input
 
433
     */
 
434
    public final float averageBytesPerChar() {
 
435
        return averageBytesPerChar;
 
436
    }
 
437
 
 
438
    /**
 
439
     * Returns the maximum number of bytes that will be produced for each
 
440
     * character of input.  This value may be used to compute the worst-case size
 
441
     * of the output buffer required for a given input sequence. </p>
 
442
     *
 
443
     * @return  The maximum number of bytes that will be produced per
 
444
     *          character of input
 
445
     */
 
446
    public final float maxBytesPerChar() {
 
447
        return maxBytesPerChar;
 
448
    }
 
449
 
 
450
    /**
 
451
     * Encodes as many characters as possible from the given input buffer,
 
452
     * writing the results to the given output buffer.
 
453
     *
 
454
     * <p> The buffers are read from, and written to, starting at their current
 
455
     * positions.  At most {@link Buffer#remaining in.remaining()} characters
 
456
     * will be read and at most {@link Buffer#remaining out.remaining()}
 
457
     * bytes will be written.  The buffers' positions will be advanced to
 
458
     * reflect the characters read and the bytes written, but their marks and
 
459
     * limits will not be modified.
 
460
     *
 
461
     * <p> In addition to reading characters from the input buffer and writing
 
462
     * bytes to the output buffer, this method returns a {@link CoderResult}
 
463
     * object to describe its reason for termination:
 
464
     *
 
465
     * <ul>
 
466
     *
 
467
     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
 
468
     *   input buffer as possible has been encoded.  If there is no further
 
469
     *   input then the invoker can proceed to the next step of the
 
470
     *   <a href="#steps">encoding operation</a>.  Otherwise this method
 
471
     *   should be invoked again with further input.  </p></li>
 
472
     *
 
473
     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
 
474
     *   insufficient space in the output buffer to encode any more characters.
 
475
     *   This method should be invoked again with an output buffer that has
 
476
     *   more {@linkplain Buffer#remaining remaining} bytes. This is
 
477
     *   typically done by draining any encoded bytes from the output
 
478
     *   buffer.  </p></li>
 
479
     *
 
480
     *   <li><p> A {@link CoderResult#malformedForLength
 
481
     *   </code>malformed-input<code>} result indicates that a malformed-input
 
482
     *   error has been detected.  The malformed characters begin at the input
 
483
     *   buffer's (possibly incremented) position; the number of malformed
 
484
     *   characters may be determined by invoking the result object's {@link
 
485
     *   CoderResult#length() length} method.  This case applies only if the
 
486
     *   {@link #onMalformedInput </code>malformed action<code>} of this encoder
 
487
     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
 
488
     *   will be ignored or replaced, as requested.  </p></li>
 
489
     *
 
490
     *   <li><p> An {@link CoderResult#unmappableForLength
 
491
     *   </code>unmappable-character<code>} result indicates that an
 
492
     *   unmappable-character error has been detected.  The characters that
 
493
     *   encode the unmappable character begin at the input buffer's (possibly
 
494
     *   incremented) position; the number of such characters may be determined
 
495
     *   by invoking the result object's {@link CoderResult#length() length}
 
496
     *   method.  This case applies only if the {@link #onUnmappableCharacter
 
497
     *   </code>unmappable action<code>} of this encoder is {@link
 
498
     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
 
499
     *   ignored or replaced, as requested.  </p></li>
 
500
     *
 
501
     * </ul>
 
502
     *
 
503
     * In any case, if this method is to be reinvoked in the same encoding
 
504
     * operation then care should be taken to preserve any characters remaining
 
505
     * in the input buffer so that they are available to the next invocation.
 
506
     *
 
507
     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
 
508
     * the invoker can provide further input beyond that contained in the given
 
509
     * input buffer.  If there is a possibility of providing additional input
 
510
     * then the invoker should pass <tt>false</tt> for this parameter; if there
 
511
     * is no possibility of providing further input then the invoker should
 
512
     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
 
513
     * common, to pass <tt>false</tt> in one invocation and later discover that
 
514
     * no further input was actually available.  It is critical, however, that
 
515
     * the final invocation of this method in a sequence of invocations always
 
516
     * pass <tt>true</tt> so that any remaining unencoded input will be treated
 
517
     * as being malformed.
 
518
     *
 
519
     * <p> This method works by invoking the {@link #encodeLoop encodeLoop}
 
520
     * method, interpreting its results, handling error conditions, and
 
521
     * reinvoking it as necessary.  </p>
 
522
     *
 
523
     *
 
524
     * @param  in
 
525
     *         The input character buffer
 
526
     *
 
527
     * @param  out
 
528
     *         The output byte buffer
 
529
     *
 
530
     * @param  endOfInput
 
531
     *         <tt>true</tt> if, and only if, the invoker can provide no
 
532
     *         additional input characters beyond those in the given buffer
 
533
     *
 
534
     * @return  A coder-result object describing the reason for termination
 
535
     *
 
536
     * @throws  IllegalStateException
 
537
     *          If an encoding operation is already in progress and the previous
 
538
     *          step was an invocation neither of the {@link #reset reset}
 
539
     *          method, nor of this method with a value of <tt>false</tt> for
 
540
     *          the <tt>endOfInput</tt> parameter, nor of this method with a
 
541
     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
 
542
     *          but a return value indicating an incomplete encoding operation
 
543
     *
 
544
     * @throws  CoderMalfunctionError
 
545
     *          If an invocation of the encodeLoop method threw
 
546
     *          an unexpected exception
 
547
     */
 
548
    public final CoderResult encode(CharBuffer in, ByteBuffer out,
 
549
                                    boolean endOfInput)
 
550
    {
 
551
        int newState = endOfInput ? ST_END : ST_CODING;
 
552
        if ((state != ST_RESET) && (state != ST_CODING)
 
553
            && !(endOfInput && (state == ST_END)))
 
554
            throwIllegalStateException(state, newState);
 
555
        state = newState;
 
556
 
 
557
        for (;;) {
 
558
 
 
559
            CoderResult cr;
 
560
            try {
 
561
                cr = encodeLoop(in, out);
 
562
            } catch (BufferUnderflowException x) {
 
563
                throw new CoderMalfunctionError(x);
 
564
            } catch (BufferOverflowException x) {
 
565
                throw new CoderMalfunctionError(x);
 
566
            }
 
567
 
 
568
            if (cr.isOverflow())
 
569
                return cr;
 
570
 
 
571
            if (cr.isUnderflow()) {
 
572
                if (endOfInput && in.hasRemaining()) {
 
573
                    cr = CoderResult.malformedForLength(in.remaining());
 
574
                    // Fall through to malformed-input case
 
575
                } else {
 
576
                    return cr;
 
577
                }
 
578
            }
 
579
 
 
580
            CodingErrorAction action = null;
 
581
            if (cr.isMalformed())
 
582
                action = malformedInputAction;
 
583
            else if (cr.isUnmappable())
 
584
                action = unmappableCharacterAction;
 
585
            else
 
586
                assert false : cr.toString();
 
587
 
 
588
            if (action == CodingErrorAction.REPORT)
 
589
                return cr;
 
590
 
 
591
            if (action == CodingErrorAction.REPLACE) {
 
592
                if (out.remaining() < replacement.length)
 
593
                    return CoderResult.OVERFLOW;
 
594
                out.put(replacement);
 
595
            }
 
596
 
 
597
            if ((action == CodingErrorAction.IGNORE)
 
598
                || (action == CodingErrorAction.REPLACE)) {
 
599
                // Skip erroneous input either way
 
600
                in.position(in.position() + cr.length());
 
601
                continue;
 
602
            }
 
603
 
 
604
            assert false;
 
605
        }
 
606
 
 
607
    }
 
608
 
 
609
    /**
 
610
     * Flushes this encoder.
 
611
     *
 
612
     * <p> Some encoders maintain internal state and may need to write some
 
613
     * final bytes to the output buffer once the overall input sequence has
 
614
     * been read.
 
615
     *
 
616
     * <p> Any additional output is written to the output buffer beginning at
 
617
     * its current position.  At most {@link Buffer#remaining out.remaining()}
 
618
     * bytes will be written.  The buffer's position will be advanced
 
619
     * appropriately, but its mark and limit will not be modified.
 
620
     *
 
621
     * <p> If this method completes successfully then it returns {@link
 
622
     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
 
623
     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
 
624
     * then this method must be invoked again, with an output buffer that has
 
625
     * more room, in order to complete the current <a href="#steps">encoding
 
626
     * operation</a>.
 
627
     *
 
628
     * <p> If this encoder has already been flushed then invoking this method
 
629
     * has no effect.
 
630
     *
 
631
     * <p> This method invokes the {@link #implFlush implFlush} method to
 
632
     * perform the actual flushing operation.  </p>
 
633
     *
 
634
     * @param  out
 
635
     *         The output byte buffer
 
636
     *
 
637
     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
 
638
     *          {@link CoderResult#OVERFLOW}
 
639
     *
 
640
     * @throws  IllegalStateException
 
641
     *          If the previous step of the current encoding operation was an
 
642
     *          invocation neither of the {@link #flush flush} method nor of
 
643
     *          the three-argument {@link
 
644
     *          #encode(CharBuffer,ByteBuffer,boolean) encode} method
 
645
     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
 
646
     *          parameter
 
647
     */
 
648
    public final CoderResult flush(ByteBuffer out) {
 
649
        if (state == ST_END) {
 
650
            CoderResult cr = implFlush(out);
 
651
            if (cr.isUnderflow())
 
652
                state = ST_FLUSHED;
 
653
            return cr;
 
654
        }
 
655
 
 
656
        if (state != ST_FLUSHED)
 
657
            throwIllegalStateException(state, ST_FLUSHED);
 
658
 
 
659
        return CoderResult.UNDERFLOW; // Already flushed
 
660
    }
 
661
 
 
662
    /**
 
663
     * Flushes this encoder.
 
664
     *
 
665
     * <p> The default implementation of this method does nothing, and always
 
666
     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
 
667
     * by encoders that may need to write final bytes to the output buffer
 
668
     * once the entire input sequence has been read. </p>
 
669
     *
 
670
     * @param  out
 
671
     *         The output byte buffer
 
672
     *
 
673
     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
 
674
     *          {@link CoderResult#OVERFLOW}
 
675
     */
 
676
    protected CoderResult implFlush(ByteBuffer out) {
 
677
        return CoderResult.UNDERFLOW;
 
678
    }
 
679
 
 
680
    /**
 
681
     * Resets this encoder, clearing any internal state.
 
682
     *
 
683
     * <p> This method resets charset-independent state and also invokes the
 
684
     * {@link #implReset() implReset} method in order to perform any
 
685
     * charset-specific reset actions.  </p>
 
686
     *
 
687
     * @return  This encoder
 
688
     *
 
689
     */
 
690
    public final CharsetEncoder reset() {
 
691
        implReset();
 
692
        state = ST_RESET;
 
693
        return this;
 
694
    }
 
695
 
 
696
    /**
 
697
     * Resets this encoder, clearing any charset-specific internal state.
 
698
     *
 
699
     * <p> The default implementation of this method does nothing.  This method
 
700
     * should be overridden by encoders that maintain internal state.  </p>
 
701
     */
 
702
    protected void implReset() { }
 
703
 
 
704
    /**
 
705
     * Encodes one or more characters into one or more bytes.
 
706
     *
 
707
     * <p> This method encapsulates the basic encoding loop, encoding as many
 
708
     * characters as possible until it either runs out of input, runs out of room
 
709
     * in the output buffer, or encounters an encoding error.  This method is
 
710
     * invoked by the {@link #encode encode} method, which handles result
 
711
     * interpretation and error recovery.
 
712
     *
 
713
     * <p> The buffers are read from, and written to, starting at their current
 
714
     * positions.  At most {@link Buffer#remaining in.remaining()} characters
 
715
     * will be read, and at most {@link Buffer#remaining out.remaining()}
 
716
     * bytes will be written.  The buffers' positions will be advanced to
 
717
     * reflect the characters read and the bytes written, but their marks and
 
718
     * limits will not be modified.
 
719
     *
 
720
     * <p> This method returns a {@link CoderResult} object to describe its
 
721
     * reason for termination, in the same manner as the {@link #encode encode}
 
722
     * method.  Most implementations of this method will handle encoding errors
 
723
     * by returning an appropriate result object for interpretation by the
 
724
     * {@link #encode encode} method.  An optimized implementation may instead
 
725
     * examine the relevant error action and implement that action itself.
 
726
     *
 
727
     * <p> An implementation of this method may perform arbitrary lookahead by
 
728
     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
 
729
     * input.  </p>
 
730
     *
 
731
     * @param  in
 
732
     *         The input character buffer
 
733
     *
 
734
     * @param  out
 
735
     *         The output byte buffer
 
736
     *
 
737
     * @return  A coder-result object describing the reason for termination
 
738
     */
 
739
    protected abstract CoderResult encodeLoop(CharBuffer in,
 
740
                                              ByteBuffer out);
 
741
 
 
742
    /**
 
743
     * Convenience method that encodes the remaining content of a single input
 
744
     * character buffer into a newly-allocated byte buffer.
 
745
     *
 
746
     * <p> This method implements an entire <a href="#steps">encoding
 
747
     * operation</a>; that is, it resets this encoder, then it encodes the
 
748
     * characters in the given character buffer, and finally it flushes this
 
749
     * encoder.  This method should therefore not be invoked if an encoding
 
750
     * operation is already in progress.  </p>
 
751
     *
 
752
     * @param  in
 
753
     *         The input character buffer
 
754
     *
 
755
     * @return A newly-allocated byte buffer containing the result of the
 
756
     *         encoding operation.  The buffer's position will be zero and its
 
757
     *         limit will follow the last byte written.
 
758
     *
 
759
     * @throws  IllegalStateException
 
760
     *          If an encoding operation is already in progress
 
761
     *
 
762
     * @throws  MalformedInputException
 
763
     *          If the character sequence starting at the input buffer's current
 
764
     *          position is not a legal sixteen-bit Unicode sequence and the current malformed-input action
 
765
     *          is {@link CodingErrorAction#REPORT}
 
766
     *
 
767
     * @throws  UnmappableCharacterException
 
768
     *          If the character sequence starting at the input buffer's current
 
769
     *          position cannot be mapped to an equivalent byte sequence and
 
770
     *          the current unmappable-character action is {@link
 
771
     *          CodingErrorAction#REPORT}
 
772
     */
 
773
    public final ByteBuffer encode(CharBuffer in)
 
774
        throws CharacterCodingException
 
775
    {
 
776
        int n = (int)(in.remaining() * averageBytesPerChar());
 
777
        ByteBuffer out = ByteBuffer.allocate(n);
 
778
 
 
779
        if ((n == 0) && (in.remaining() == 0))
 
780
            return out;
 
781
        reset();
 
782
        for (;;) {
 
783
            CoderResult cr = in.hasRemaining() ?
 
784
                encode(in, out, true) : CoderResult.UNDERFLOW;
 
785
            if (cr.isUnderflow())
 
786
                cr = flush(out);
 
787
 
 
788
            if (cr.isUnderflow())
 
789
                break;
 
790
            if (cr.isOverflow()) {
 
791
                n = 2*n + 1;    // Ensure progress; n might be 0!
 
792
                ByteBuffer o = ByteBuffer.allocate(n);
 
793
                out.flip();
 
794
                o.put(out);
 
795
                out = o;
 
796
                continue;
 
797
            }
 
798
            cr.throwException();
 
799
        }
 
800
        out.flip();
 
801
        return out;
 
802
    }
 
803
 
 
804
 
 
805
 
 
806
 
 
807
 
 
808
 
 
809
 
 
810
 
 
811
 
 
812
 
 
813
 
 
814
 
 
815
 
 
816
 
 
817
 
 
818
 
 
819
 
 
820
 
 
821
 
 
822
 
 
823
 
 
824
 
 
825
 
 
826
 
 
827
 
 
828
 
 
829
 
 
830
 
 
831
 
 
832
 
 
833
 
 
834
 
 
835
 
 
836
 
 
837
 
 
838
 
 
839
 
 
840
 
 
841
 
 
842
 
 
843
 
 
844
 
 
845
 
 
846
 
 
847
 
 
848
 
 
849
 
 
850
 
 
851
 
 
852
 
 
853
 
 
854
 
 
855
 
 
856
 
 
857
 
 
858
 
 
859
 
 
860
 
 
861
 
 
862
 
 
863
 
 
864
 
 
865
 
 
866
 
 
867
 
 
868
 
 
869
 
 
870
 
 
871
 
 
872
 
 
873
 
 
874
 
 
875
 
 
876
 
 
877
 
 
878
 
 
879
 
 
880
 
 
881
 
 
882
    private boolean canEncode(CharBuffer cb) {
 
883
        if (state == ST_FLUSHED)
 
884
            reset();
 
885
        else if (state != ST_RESET)
 
886
            throwIllegalStateException(state, ST_CODING);
 
887
        CodingErrorAction ma = malformedInputAction();
 
888
        CodingErrorAction ua = unmappableCharacterAction();
 
889
        try {
 
890
            onMalformedInput(CodingErrorAction.REPORT);
 
891
            onUnmappableCharacter(CodingErrorAction.REPORT);
 
892
            encode(cb);
 
893
        } catch (CharacterCodingException x) {
 
894
            return false;
 
895
        } finally {
 
896
            onMalformedInput(ma);
 
897
            onUnmappableCharacter(ua);
 
898
            reset();
 
899
        }
 
900
        return true;
 
901
    }
 
902
 
 
903
    /**
 
904
     * Tells whether or not this encoder can encode the given character.
 
905
     *
 
906
     * <p> This method returns <tt>false</tt> if the given character is a
 
907
     * surrogate character; such characters can be interpreted only when they
 
908
     * are members of a pair consisting of a high surrogate followed by a low
 
909
     * surrogate.  The {@link #canEncode(java.lang.CharSequence)
 
910
     * canEncode(CharSequence)} method may be used to test whether or not a
 
911
     * character sequence can be encoded.
 
912
     *
 
913
     * <p> This method may modify this encoder's state; it should therefore not
 
914
     * be invoked if an <a href="#steps">encoding operation</a> is already in
 
915
     * progress.
 
916
     *
 
917
     * <p> The default implementation of this method is not very efficient; it
 
918
     * should generally be overridden to improve performance.  </p>
 
919
     *
 
920
     * @return  <tt>true</tt> if, and only if, this encoder can encode
 
921
     *          the given character
 
922
     *
 
923
     * @throws  IllegalStateException
 
924
     *          If an encoding operation is already in progress
 
925
     */
 
926
    public boolean canEncode(char c) {
 
927
        CharBuffer cb = CharBuffer.allocate(1);
 
928
        cb.put(c);
 
929
        cb.flip();
 
930
        return canEncode(cb);
 
931
    }
 
932
 
 
933
    /**
 
934
     * Tells whether or not this encoder can encode the given character
 
935
     * sequence.
 
936
     *
 
937
     * <p> If this method returns <tt>false</tt> for a particular character
 
938
     * sequence then more information about why the sequence cannot be encoded
 
939
     * may be obtained by performing a full <a href="#steps">encoding
 
940
     * operation</a>.
 
941
     *
 
942
     * <p> This method may modify this encoder's state; it should therefore not
 
943
     * be invoked if an encoding operation is already in progress.
 
944
     *
 
945
     * <p> The default implementation of this method is not very efficient; it
 
946
     * should generally be overridden to improve performance.  </p>
 
947
     *
 
948
     * @return  <tt>true</tt> if, and only if, this encoder can encode
 
949
     *          the given character without throwing any exceptions and without
 
950
     *          performing any replacements
 
951
     *
 
952
     * @throws  IllegalStateException
 
953
     *          If an encoding operation is already in progress
 
954
     */
 
955
    public boolean canEncode(CharSequence cs) {
 
956
        CharBuffer cb;
 
957
        if (cs instanceof CharBuffer)
 
958
            cb = ((CharBuffer)cs).duplicate();
 
959
        else
 
960
            cb = CharBuffer.wrap(cs.toString());
 
961
        return canEncode(cb);
 
962
    }
 
963
 
 
964
 
 
965
 
 
966
 
 
967
    private void throwIllegalStateException(int from, int to) {
 
968
        throw new IllegalStateException("Current state = " + stateNames[from]
 
969
                                        + ", new state = " + stateNames[to]);
 
970
    }
 
971
 
 
972
}