internal virtual CoderResult Get(int len) { lock (this) { if (len <= 0) { throw new IllegalArgumentException("Non-positive length"); } Integer k = new Integer(len); WeakReference <CoderResult> w; CoderResult e = null; if (Cache == null) { Cache = new Dictionary <Integer, WeakReference <CoderResult> >(); } else if ((w = Cache[k]) != null) { e = w.get(); } if (e == null) { e = Create(len); Cache[k] = new WeakReference <CoderResult>(e); } return(e); } }
/// <summary> /// Flushes this decoder. /// /// <para> Some decoders maintain internal state and may need to write some /// final characters to the output buffer once the overall input sequence has /// been read. /// /// </para> /// <para> Any additional output is written to the output buffer beginning at /// its current position. At most <seealso cref="Buffer#remaining out.remaining()"/> /// characters will be written. The buffer's position will be advanced /// appropriately, but its mark and limit will not be modified. /// /// </para> /// <para> If this method completes successfully then it returns {@link /// CoderResult#UNDERFLOW}. If there is insufficient room in the output /// buffer then it returns <seealso cref="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 <a href="#steps">decoding /// operation</a>. /// /// </para> /// <para> If this decoder has already been flushed then invoking this method /// has no effect. /// /// </para> /// <para> This method invokes the <seealso cref="#implFlush implFlush"/> method to /// perform the actual flushing operation. </para> /// </summary> /// <param name="out"> /// The output character buffer /// </param> /// <returns> A coder-result object, either <seealso cref="CoderResult#UNDERFLOW"/> or /// <seealso cref="CoderResult#OVERFLOW"/> /// </returns> /// <exception cref="IllegalStateException"> /// If the previous step of the current decoding operation was an /// invocation neither of the <seealso cref="#flush flush"/> method nor of /// the three-argument {@link /// #decode(ByteBuffer,CharBuffer,boolean) decode} method /// with a value of <tt>true</tt> for the <tt>endOfInput</tt> /// parameter </exception> public CoderResult Flush(CharBuffer @out) { if (State == ST_END) { CoderResult cr = ImplFlush(@out); if (cr.Underflow) { State = ST_FLUSHED; } return(cr); } if (State != ST_FLUSHED) { ThrowIllegalStateException(State, ST_FLUSHED); } return(CoderResult.UNDERFLOW); // Already flushed }
/// <summary> /// Tells whether or not the given byte array is a legal replacement value /// for this encoder. /// /// <para> 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. /// /// </para> /// <para> The default implementation of this method is not very efficient; it /// should generally be overridden to improve performance. </para> /// </summary> /// <param name="repl"> The byte array to be tested /// </param> /// <returns> <tt>true</tt> if, and only if, the given byte array /// is a legal replacement value for this encoder </returns> public virtual bool IsLegalReplacement(sbyte[] repl) { WeakReference <CharsetDecoder> wr = CachedDecoder; CharsetDecoder dec = null; if ((wr == null) || ((dec = wr.get()) == null)) { dec = Charset().NewDecoder(); dec.OnMalformedInput(CodingErrorAction.REPORT); dec.OnUnmappableCharacter(CodingErrorAction.REPORT); CachedDecoder = new WeakReference <CharsetDecoder>(dec); } else { dec.Reset(); } ByteBuffer bb = ByteBuffer.Wrap(repl); CharBuffer cb = CharBuffer.Allocate((int)(bb.Remaining() * dec.MaxCharsPerByte())); CoderResult cr = dec.Decode(bb, cb, true); return(!cr.Error); }
/// <summary> /// Convenience method that decodes the remaining content of a single input /// byte buffer into a newly-allocated character buffer. /// /// <para> This method implements an entire <a href="#steps">decoding /// operation</a>; that is, it resets this decoder, then it decodes the /// bytes in the given byte buffer, and finally it flushes this /// decoder. This method should therefore not be invoked if a decoding /// operation is already in progress. </para> /// </summary> /// <param name="in"> /// The input byte buffer /// </param> /// <returns> A newly-allocated character buffer containing the result of the /// decoding operation. The buffer's position will be zero and its /// limit will follow the last character written. /// </returns> /// <exception cref="IllegalStateException"> /// If a decoding operation is already in progress /// </exception> /// <exception cref="MalformedInputException"> /// If the byte sequence starting at the input buffer's current /// position is not legal for this charset and the current malformed-input action /// is <seealso cref="CodingErrorAction#REPORT"/> /// </exception> /// <exception cref="UnmappableCharacterException"> /// If the byte sequence starting at the input buffer's current /// position cannot be mapped to an equivalent character sequence and /// the current unmappable-character action is {@link /// CodingErrorAction#REPORT} </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public final java.nio.CharBuffer decode(java.nio.ByteBuffer in) throws CharacterCodingException public CharBuffer Decode(ByteBuffer @in) { int n = (int)(@in.Remaining() * AverageCharsPerByte()); CharBuffer @out = CharBuffer.Allocate(n); if ((n == 0) && (@in.Remaining() == 0)) { return(@out); } Reset(); for (;;) { CoderResult cr = @in.HasRemaining() ? Decode(@in, @out, true) : CoderResult.UNDERFLOW; if (cr.Underflow) { cr = Flush(@out); } if (cr.Underflow) { break; } if (cr.Overflow) { n = 2 * n + 1; // Ensure progress; n might be 0! CharBuffer o = CharBuffer.Allocate(n); @out.Flip(); o.Put(@out); @out = o; continue; } cr.ThrowException(); } @out.Flip(); return(@out); }
/// <summary> /// Decodes as many bytes as possible from the given input buffer, /// writing the results to the given output buffer. /// /// <para> The buffers are read from, and written to, starting at their current /// positions. At most <seealso cref="Buffer#remaining in.remaining()"/> bytes /// will be read and at most <seealso cref="Buffer#remaining out.remaining()"/> /// characters will be written. The buffers' positions will be advanced to /// reflect the bytes read and the characters written, but their marks and /// limits will not be modified. /// /// </para> /// <para> In addition to reading bytes from the input buffer and writing /// characters to the output buffer, this method returns a <seealso cref="CoderResult"/> /// object to describe its reason for termination: /// /// <ul> /// /// </para> /// <li><para> <seealso cref="CoderResult#UNDERFLOW"/> indicates that as much of the /// input buffer as possible has been decoded. If there is no further /// input then the invoker can proceed to the next step of the /// <a href="#steps">decoding operation</a>. Otherwise this method /// should be invoked again with further input. </para></li> /// /// <li><para> <seealso cref="CoderResult#OVERFLOW"/> indicates that there is /// insufficient space in the output buffer to decode any more bytes. /// This method should be invoked again with an output buffer that has /// more <seealso cref="Buffer#remaining remaining"/> characters. This is /// typically done by draining any decoded characters from the output /// buffer. </para></li> /// /// <li><para> A {@link CoderResult#malformedForLength /// malformed-input} result indicates that a malformed-input /// error has been detected. The malformed bytes begin at the input /// buffer's (possibly incremented) position; the number of malformed /// bytes may be determined by invoking the result object's {@link /// CoderResult#length() length} method. This case applies only if the /// <seealso cref="#onMalformedInput malformed action"/> of this decoder /// is <seealso cref="CodingErrorAction#REPORT"/>; otherwise the malformed input /// will be ignored or replaced, as requested. </para></li> /// /// <li><para> An {@link CoderResult#unmappableForLength /// unmappable-character} result indicates that an /// unmappable-character error has been detected. The bytes that /// decode the unmappable character begin at the input buffer's (possibly /// incremented) position; the number of such bytes may be determined /// by invoking the result object's <seealso cref="CoderResult#length() length"/> /// method. This case applies only if the {@link #onUnmappableCharacter /// unmappable action} of this decoder is {@link /// CodingErrorAction#REPORT}; otherwise the unmappable character will be /// ignored or replaced, as requested. </para></li> /// /// </ul> /// /// In any case, if this method is to be reinvoked in the same decoding /// operation then care should be taken to preserve any bytes remaining /// in the input buffer so that they are available to the next invocation. /// /// <para> The <tt>endOfInput</tt> 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 <tt>false</tt> for this parameter; if there /// is no possibility of providing further input then the invoker should /// pass <tt>true</tt>. It is not erroneous, and in fact it is quite /// common, to pass <tt>false</tt> 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 <tt>true</tt> so that any remaining undecoded input will be treated /// as being malformed. /// /// </para> /// <para> This method works by invoking the <seealso cref="#decodeLoop decodeLoop"/> /// method, interpreting its results, handling error conditions, and /// reinvoking it as necessary. </para> /// /// </summary> /// <param name="in"> /// The input byte buffer /// </param> /// <param name="out"> /// The output character buffer /// </param> /// <param name="endOfInput"> /// <tt>true</tt> if, and only if, the invoker can provide no /// additional input bytes beyond those in the given buffer /// </param> /// <returns> A coder-result object describing the reason for termination /// </returns> /// <exception cref="IllegalStateException"> /// If a decoding operation is already in progress and the previous /// step was an invocation neither of the <seealso cref="#reset reset"/> /// method, nor of this method with a value of <tt>false</tt> for /// the <tt>endOfInput</tt> parameter, nor of this method with a /// value of <tt>true</tt> for the <tt>endOfInput</tt> parameter /// but a return value indicating an incomplete decoding operation /// </exception> /// <exception cref="CoderMalfunctionError"> /// If an invocation of the decodeLoop method threw /// an unexpected exception </exception> public CoderResult Decode(ByteBuffer @in, CharBuffer @out, bool endOfInput) { int newState = endOfInput ? ST_END : ST_CODING; if ((State != ST_RESET) && (State != ST_CODING) && !(endOfInput && (State == ST_END))) { ThrowIllegalStateException(State, newState); } State = newState; for (;;) { CoderResult cr; try { cr = DecodeLoop(@in, @out); } catch (BufferUnderflowException x) { throw new CoderMalfunctionError(x); } catch (BufferOverflowException x) { throw new CoderMalfunctionError(x); } if (cr.Overflow) { return(cr); } if (cr.Underflow) { if (endOfInput && @in.HasRemaining()) { cr = CoderResult.MalformedForLength(@in.Remaining()); // Fall through to malformed-input case } else { return(cr); } } CodingErrorAction action = null; if (cr.Malformed) { action = MalformedInputAction_Renamed; } else if (cr.Unmappable) { action = UnmappableCharacterAction_Renamed; } else { Debug.Assert(false, cr.ToString()); } if (action == CodingErrorAction.REPORT) { return(cr); } if (action == CodingErrorAction.REPLACE) { if (@out.Remaining() < Replacement_Renamed.Length()) { return(CoderResult.OVERFLOW); } @out.Put(Replacement_Renamed); } if ((action == CodingErrorAction.IGNORE) || (action == CodingErrorAction.REPLACE)) { // Skip erroneous input either way @in.Position(@in.Position() + cr.Length()); continue; } Debug.Assert(false); } }