Beispiel #1
0
        /*
         * This is a facade method for the encoding operation.
         * <p />
         * This method encodes the remaining character sequence of the given
         * character buffer into a new byte buffer. This method performs a complete
         * encoding operation, resets at first, then encodes, and flushes at last.
         * <p />
         * This method should not be invoked if another encode operation is ongoing.
         *
         * @param in
         *            the input buffer.
         * @return a new <code>ByteBuffer</code> containing the bytes produced by
         *         this encoding operation. The buffer's limit will be the position
         *         of the last byte in the buffer, and the position will be zero.
         * @throws IllegalStateException
         *             if another encoding operation is ongoing.
         * @throws MalformedInputException
         *             if an illegal input character sequence for this charset is
         *             encountered, and the action for malformed error is
         *             {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}
         * @throws UnmappableCharacterException
         *             if a legal but unmappable input character sequence for this
         *             charset is encountered, and the action for unmappable
         *             character error is
         *             {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.
         *             Unmappable means the Unicode character sequence at the input
         *             buffer's current position cannot be mapped to a equivalent
         *             byte sequence.
         * @throws CharacterCodingException
         *             if other exception happened during the encode operation.
         */
        public ByteBuffer encode(CharBuffer inJ) //throws CharacterCodingException
        {
            if (inJ.remaining() == 0)
            {
                return(ByteBuffer.allocate(0));
            }
            reset();
            int         length = (int)(inJ.remaining() * averBytes);
            ByteBuffer  output = ByteBuffer.allocate(length);
            CoderResult result = null;

            while (true)
            {
                result = encode(inJ, output, false);
                if (result == CoderResult.UNDERFLOW)
                {
                    break;
                }
                else if (result == CoderResult.OVERFLOW)
                {
                    output = allocateMore(output);
                    continue;
                }
                checkCoderResult(result);
            }
            result = encode(inJ, output, true);
            checkCoderResult(result);

            while (true)
            {
                result = flush(output);
                if (result == CoderResult.UNDERFLOW)
                {
                    output.flip();
                    break;
                }
                else if (result == CoderResult.OVERFLOW)
                {
                    output = allocateMore(output);
                    continue;
                }
                checkCoderResult(result);
                output.flip();
                if (result.isMalformed())
                {
                    throw new MalformedInputException(result.length());
                }
                else if (result.isUnmappable())
                {
                    throw new UnmappableCharacterException(result.length());
                }
                break;
            }
            status   = READY;
            finished = true;
            return(output);
        }
Beispiel #2
0
 /*
  * checks the result whether it needs to throw CharacterCodingException.
  */
 private void checkCoderResult(CoderResult result)// throws CharacterCodingException
 {
     if (malformAction == CodingErrorAction.REPORT && result.isMalformed())
     {
         throw new MalformedInputException(result.length());
     }
     else if (unmapAction == CodingErrorAction.REPORT && result.isUnmappable())
     {
         throw new UnmappableCharacterException(result.length());
     }
 }
Beispiel #3
0
        /*
         * Flushes this encoder.
         * <p />
         * This method will call {@link #implFlush(ByteBuffer) implFlush}. Some
         * encoders may need to write some bytes to the output buffer when they have
         * read all input characters, subclasses can overridden
         * {@link #implFlush(ByteBuffer) implFlush} to perform writing action.
         * <p />
         * The maximum number of written bytes won't larger than
         * {@link ByteBuffer#remaining() out.remaining()}. If some encoder wants to
         * write more bytes than the output buffer's available remaining space, then
         * <code>CoderResult.OVERFLOW</code> will be returned, and this method
         * must be called again with a byte buffer that has free space. Otherwise
         * this method will return <code>CoderResult.UNDERFLOW</code>, which
         * means one encoding process has been completed successfully.
         * <p />
         * During the flush, the output buffer's position will be changed
         * accordingly, while its mark and limit will be intact.
         *
         * @param out
         *            the given output buffer.
         * @return <code>CoderResult.UNDERFLOW</code> or
         *         <code>CoderResult.OVERFLOW</code>.
         * @throws IllegalStateException
         *             if this encoder hasn't read all input characters during one
         *             encoding process, which means neither after calling
         *             {@link #encode(CharBuffer) encode(CharBuffer)} nor after
         *             calling {@link #encode(CharBuffer, ByteBuffer, boolean)
         *             encode(CharBuffer, ByteBuffer, boolean)} with {@code true}
         *             for the last boolean parameter.
         */
        public CoderResult flush(ByteBuffer outJ)
        {
            if (status != END && status != READY)
            {
                throw new java.lang.IllegalStateException();
            }
            CoderResult result = implFlush(outJ);

            if (result == CoderResult.UNDERFLOW)
            {
                status = FLUSH;
            }
            return(result);
        }
 /**
  * Gets a <code>CoderResult</code> object indicating an unmappable
  * character error.
  *
  * @param length
  *            the length of the input unit sequence denoting the unmappable
  *            character.
  * @return a <code>CoderResult</code> object indicating an unmappable
  *         character error.
  * @throws IllegalArgumentException
  *             if <code>length</code> is non-positive.
  */
 public static CoderResult unmappableForLength(int length)
 {
     lock (lockObject) {
         if (length > 0)
         {
             int key = length;
             lock (_unmappableErrors) {
                 CoderResult r = _unmappableErrors.get(key);
                 if (null == r)
                 {
                     r = new CoderResult(TYPE_UNMAPPABLE_CHAR, length);
                     _unmappableErrors.put(key, r);
                 }
                 return(r);
             }
         }
         throw new java.lang.IllegalArgumentException("The length must be positive: " + length + "."); //$NON-NLS-1$
     }
 }
 /**
  * Gets a <code>CoderResult</code> object indicating a malformed-input
  * error.
  *
  * @param length
  *            the length of the malformed-input.
  * @return a <code>CoderResult</code> object indicating a malformed-input
  *         error.
  * @throws IllegalArgumentException
  *             if <code>length</code> is non-positive.
  */
 public static CoderResult malformedForLength(int length)
 {
     lock (lockObject) {
         if (length > 0)
         {
             int key = length;
             lock (_malformedErrors) {
                 CoderResult r = _malformedErrors.get(key);
                 if (null == r)
                 {
                     r = new CoderResult(TYPE_MALFORMED_INPUT, length);
                     _malformedErrors.put(key, r);
                 }
                 return(r);
             }
         }
         throw new java.lang.IllegalArgumentException("The length must be positive: " + length + "."); //$NON-NLS-1$
     }
 }
Beispiel #6
0
        /*
         * This is a facade method for the decoding operation.
         * <p>
         * This method decodes the remaining byte sequence of the given byte buffer
         * into a new character buffer. This method performs a complete decoding
         * operation, resets at first, then decodes, and flushes at last.
         * <p>
         * This method should not be invoked while another {@code decode} operation
         * is ongoing.
         *
         * @param in
         *            the input buffer.
         * @return a new <code>CharBuffer</code> containing the the characters
         *         produced by this decoding operation. The buffer's limit will be
         *         the position of the last character in the buffer, and the
         *         position will be zero.
         * @throws IllegalStateException
         *             if another decoding operation is ongoing.
         * @throws MalformedInputException
         *             if an illegal input byte sequence for this charset was
         *             encountered, and the action for malformed error is
         *             {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}
         * @throws UnmappableCharacterException
         *             if a legal but unmappable input byte sequence for this
         *             charset was encountered, and the action for unmappable
         *             character error is
         *             {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.
         *             Unmappable means the byte sequence at the input buffer's
         *             current position cannot be mapped to a Unicode character
         *             sequence.
         * @throws CharacterCodingException
         *             if another exception happened during the decode operation.
         */
        public java.nio.CharBuffer decode(java.nio.ByteBuffer inJ) //throws CharacterCodingException
        {
            reset();
            int length = (int)(inJ.remaining() * averChars);

            java.nio.CharBuffer output = java.nio.CharBuffer.allocate(length);
            CoderResult         result = null;

            while (true)
            {
                result = decode(inJ, output, false);
                checkCoderResult(result);
                if (result.isUnderflow())
                {
                    break;
                }
                else if (result.isOverflow())
                {
                    output = allocateMore(output);
                }
            }
            result = decode(inJ, output, true);
            checkCoderResult(result);

            while (true)
            {
                result = flush(output);
                checkCoderResult(result);
                if (result.isOverflow())
                {
                    output = allocateMore(output);
                }
                else
                {
                    break;
                }
            }

            output.flip();
            status = FLUSH;
            return(output);
        }
Beispiel #7
0
        /*
         * Checks if the given argument is legal as this encoder's replacement byte
         * array.
         *
         * The given byte array is legal if and only if it can be decode into
         * sixteen bits Unicode characters.
         *
         * This method can be overridden for performance improvement.
         *
         * @param repl
         *            the given byte array to be checked.
         * @return true if the the given argument is legal as this encoder's
         *         replacement byte array.
         */
        public bool isLegalReplacement(byte[] repl)
        {
            if (decoder == null)
            {
                decoder = cs.newDecoder();
            }

            CodingErrorAction malform = decoder.malformedInputAction();
            CodingErrorAction unmap   = decoder.unmappableCharacterAction();

            decoder.onMalformedInput(CodingErrorAction.REPORT);
            decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
            java.nio.ByteBuffer inJ  = java.nio.ByteBuffer.wrap(repl);
            java.nio.CharBuffer outJ = java.nio.CharBuffer.allocate((int)(repl.Length * decoder
                                                                          .maxCharsPerByte()));
            CoderResult result = decoder.decode(inJ, outJ, true);

            decoder.onMalformedInput(malform);
            decoder.onUnmappableCharacter(unmap);
            return(!result.isError());
        }
Beispiel #8
0
        /*
         * Encodes characters starting at the current position of the given input
         * buffer, and writes the equivalent byte sequence into the given output
         * buffer from its current position.
         * <p />
         * The buffers' position will be changed with the reading and writing
         * operation, but their limits and marks will be kept intact.
         * <p />
         * A <code>CoderResult</code> instance will be returned according to
         * following rules:
         * <ul>
         * <li>A {@link CoderResult#malformedForLength(int) malformed input} result
         * indicates that some malformed input error was encountered, and the
         * erroneous characters start at the input buffer's position and their
         * number can be got by result's {@link CoderResult#length() length}. This
         * kind of result can be returned only if the malformed action is
         * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li>
         * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that
         * as many characters as possible in the input buffer have been encoded. If
         * there is no further input and no characters left in the input buffer then
         * this task is complete. If this is not the case then the client should
         * call this method again supplying some more input characters.</li>
         * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that the
         * output buffer has been filled, while there are still some characters
         * remaining in the input buffer. This method should be invoked again with a
         * non-full output buffer.</li>
         * <li>A {@link CoderResult#unmappableForLength(int) unmappable character}
         * result indicates that some unmappable character error was encountered,
         * and the erroneous characters start at the input buffer's position and
         * their number can be got by result's {@link CoderResult#length() length}.
         * This kind of result can be returned only on
         * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li>
         * </ul>
         * <p />
         * The <code>endOfInput</code> parameter indicates if the invoker can
         * provider further input. This parameter is true if and only if the
         * characters in the current input buffer are all inputs for this encoding
         * operation. Note that it is common and won't cause an error if the invoker
         * sets false and then has no more input available, while it may cause an
         * error if the invoker always sets true in several consecutive invocations.
         * This would make the remaining input to be treated as malformed input.
         * input.
         * <p />
         * This method invokes the
         * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to
         * implement the basic encode logic for a specific charset.
         *
         * @param in
         *            the input buffer.
         * @param out
         *            the output buffer.
         * @param endOfInput
         *            true if all the input characters have been provided.
         * @return a <code>CoderResult</code> instance indicating the result.
         * @throws IllegalStateException
         *             if the encoding operation has already started or no more
         *             input is needed in this encoding process.
         * @throws CoderMalfunctionError
         *             If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop}
         *             method threw an <code>BufferUnderflowException</code> or
         *             <code>BufferUnderflowException</code>.
         */
        public CoderResult encode(java.nio.CharBuffer inJ, java.nio.ByteBuffer outJ, bool endOfInput)
        {
            //If the previous step is encode(CharBuffer), then no more input is needed
            // thus endOfInput should not be false
            if (status == READY && finished && !endOfInput)
            {
                throw new java.lang.IllegalStateException();
            }

            if ((status == FLUSH) || (!endOfInput && status == END))
            {
                throw new java.lang.IllegalStateException();
            }

            CoderResult result;

            while (true)
            {
                try {
                    result = encodeLoop(inJ, outJ);
                } catch (BufferOverflowException e) {
                    throw new CoderMalfunctionError(e);
                } catch (BufferUnderflowException e) {
                    throw new CoderMalfunctionError(e);
                }
                if (result == CoderResult.UNDERFLOW)
                {
                    status = endOfInput ? END : ONGOING;
                    if (endOfInput)
                    {
                        int remaining = inJ.remaining();
                        if (remaining > 0)
                        {
                            result = CoderResult.malformedForLength(remaining);
                        }
                        else
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        return(result);
                    }
                }
                else if (result == CoderResult.OVERFLOW)
                {
                    status = endOfInput ? END : ONGOING;
                    return(result);
                }
                CodingErrorAction action = malformAction;
                if (result.isUnmappable())
                {
                    action = unmapAction;
                }
                // If the action is IGNORE or REPLACE, we should continue
                // encoding.
                if (action == CodingErrorAction.REPLACE)
                {
                    if (outJ.remaining() < replace.Length)
                    {
                        return(CoderResult.OVERFLOW);
                    }
                    outJ.put(replace);
                }
                else
                {
                    if (action != CodingErrorAction.IGNORE)
                    {
                        return(result);
                    }
                }
                inJ.position(inJ.position() + result.length());
            }
        }
 //throws CharacterCodingException
 /*
  * checks the result whether it needs to throw CharacterCodingException.
  */
 private void checkCoderResult(CoderResult result)
 {
     if (result.isMalformed() && malformAction == CodingErrorAction.REPORT) {
         throw new MalformedInputException(result.length());
     } else if (result.isUnmappable()
             && unmapAction == CodingErrorAction.REPORT) {
         throw new UnmappableCharacterException(result.length());
     }
 }
Beispiel #10
0
        /*
         * Decodes bytes starting at the current position of the given input buffer,
         * and writes the equivalent character sequence into the given output buffer
         * from its current position.
         * <p>
         * The buffers' position will be changed with the reading and writing
         * operation, but their limits and marks will be kept intact.
         * <p>
         * A <code>CoderResult</code> instance will be returned according to
         * following rules:
         * <ul>
         * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that
         * even though not all of the input has been processed, the buffer the
         * output is being written to has reached its capacity. In the event of this
         * code being returned this method should be called once more with an
         * <code>out</code> argument that has not already been filled.</li>
         * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that
         * as many bytes as possible in the input buffer have been decoded. If there
         * is no further input and no remaining bytes in the input buffer then this
         * operation may be regarded as complete. Otherwise, this method should be
         * called once more with additional input.</li>
         * <li>A {@link CoderResult#malformedForLength(int) malformed input} result
         * indicates that some malformed input error has been encountered, and the
         * erroneous bytes start at the input buffer's position and their number can
         * be got by result's {@link CoderResult#length() length}. This kind of
         * result can be returned only if the malformed action is
         * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
         * <li>A {@link CoderResult#unmappableForLength(int) unmappable character}
         * result indicates that some unmappable character error has been
         * encountered, and the erroneous bytes start at the input buffer's position
         * and their number can be got by result's
         * {@link CoderResult#length() length}. This kind of result can be returned
         * only if the unmappable character action is
         * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
         * </ul>
         * <p>
         * The <code>endOfInput</code> parameter indicates that the invoker cannot
         * provide further input. This parameter is true if and only if the bytes in
         * current input buffer are all inputs for this decoding operation. Note
         * that it is common and won't cause an error if the invoker sets false and
         * then can't provide more input, while it may cause an error if the invoker
         * always sets true in several consecutive invocations. This would make the
         * remaining input to be treated as malformed input.
         * <p>
         * This method invokes the
         * {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop} method to
         * implement the basic decode logic for a specific charset.
         *
         * @param in
         *            the input buffer.
         * @param out
         *            the output buffer.
         * @param endOfInput
         *            true if all the input characters have been provided.
         * @return a <code>CoderResult</code> instance which indicates the reason
         *         of termination.
         * @throws IllegalStateException
         *             if decoding has started or no more input is needed in this
         *             decoding progress.
         * @throws CoderMalfunctionError
         *             if the {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop}
         *             method threw an <code>BufferUnderflowException</code> or
         *             <code>BufferOverflowException</code>.
         */
        public CoderResult decode(ByteBuffer inJ, CharBuffer outJ,
                                  bool endOfInput)
        {
            /*
             * status check
             */
            if ((status == FLUSH) || (!endOfInput && status == END))
            {
                throw new java.lang.IllegalStateException();
            }

            CoderResult result = null;

            // begin to decode
            while (true)
            {
                CodingErrorAction action = null;
                try {
                    result = decodeLoop(inJ, outJ);
                } catch (BufferOverflowException ex) {
                    // unexpected exception
                    throw new CoderMalfunctionError(ex);
                } catch (BufferUnderflowException ex) {
                    // unexpected exception
                    throw new CoderMalfunctionError(ex);
                }

                /*
                 * result handling
                 */
                if (result.isUnderflow())
                {
                    int remaining = inJ.remaining(); // WHY inJ.remaining() == 1?
                    status = endOfInput ? END : ONGOING;
                    if (endOfInput && remaining > 0)
                    {
                        result = CoderResult.malformedForLength(remaining);
                    }
                    else
                    {
                        return(result);
                    }
                }
                if (result.isOverflow())
                {
                    return(result);
                }
                // set coding error handle action
                action = malformAction;
                if (result.isUnmappable())
                {
                    action = unmapAction;
                }
                // If the action is IGNORE or REPLACE, we should continue decoding.
                if (action == CodingErrorAction.REPLACE)
                {
                    if (outJ.remaining() < replace.length())
                    {
                        return(CoderResult.OVERFLOW);
                    }
                    outJ.put(replace);
                }
                else
                {
                    if (action != CodingErrorAction.IGNORE)
                    {
                        return(result);
                    }
                }
                inJ.position(inJ.position() + result.length());
            }
        }
 /**
  * Gets a <code>CoderResult</code> object indicating an unmappable
  * character error.
  *
  * @param length
  *            the length of the input unit sequence denoting the unmappable
  *            character.
  * @return a <code>CoderResult</code> object indicating an unmappable
  *         character error.
  * @throws IllegalArgumentException
  *             if <code>length</code> is non-positive.
  */
 public static CoderResult unmappableForLength(int length)
 {
     lock (lockObject) {
         if (length > 0) {
             int key = length;
             lock (_unmappableErrors) {
                 CoderResult r = _unmappableErrors.get(key);
                 if (null == r) {
                     r = new CoderResult(TYPE_UNMAPPABLE_CHAR, length);
                     _unmappableErrors.put(key, r);
                 }
                 return r;
             }
         }
         throw new java.lang.IllegalArgumentException("The length must be positive: "+length+"."); //$NON-NLS-1$
     }
 }
 /**
  * Gets a <code>CoderResult</code> object indicating a malformed-input
  * error.
  *
  * @param length
  *            the length of the malformed-input.
  * @return a <code>CoderResult</code> object indicating a malformed-input
  *         error.
  * @throws IllegalArgumentException
  *             if <code>length</code> is non-positive.
  */
 public static CoderResult malformedForLength(int length)
 {
     lock (lockObject) {
         if (length > 0) {
             int key = length;
             lock (_malformedErrors) {
                 CoderResult r = _malformedErrors.get(key);
                 if (null == r) {
                     r = new CoderResult(TYPE_MALFORMED_INPUT, length);
                     _malformedErrors.put(key, r);
                 }
                 return r;
             }
         }
         throw new java.lang.IllegalArgumentException("The length must be positive: "+length+"."); //$NON-NLS-1$
     }
 }