Пример #1
0
        private static void Encode(BinaryCodec encoding, Stream inputStream, TextWriter outputWriter)
        {
            byte[] inputBuffer  = new byte[encoding.MinimumInputBuffer];
            char[] outputBuffer = new char[encoding.MinimumOutputBuffer];

            bool readEof        = false;
            int  inputBufferEnd = 0;
            int  inputBufferUsed;
            int  outputBufferUsed;

            BinaryEncoder encoder = encoding.GetEncoder();

            while (true)
            {
                if ((inputBufferEnd < inputBuffer.Length) && (!readEof))
                {
                    int bytesRead = inputStream.Read(inputBuffer, inputBufferEnd, inputBuffer.Length - inputBufferEnd);
                    if (bytesRead == 0)
                    {
                        readEof = true;
                    }

                    inputBufferEnd += bytesRead;
                }

                // stop when we've read EOF and Convert returns true..
                bool finished = ((encoder.Convert(inputBuffer, 0, inputBufferEnd,
                                                  outputBuffer, 0, outputBuffer.Length,
                                                  readEof,
                                                  out inputBufferUsed,
                                                  out outputBufferUsed)) && (readEof));

                // dump any output produced to outputWriter..
                outputWriter.Write(outputBuffer, 0, outputBufferUsed);

                if (finished)
                {
                    break;
                }

                // shift input as needed..
                if (inputBufferUsed != 0)
                {
                    if (inputBufferUsed < inputBufferEnd)
                    {
                        Buffer.BlockCopy(inputBuffer, inputBufferUsed, inputBuffer, 0, inputBufferEnd - inputBufferUsed);
                        inputBufferEnd -= inputBufferUsed;
                    }
                    else
                    {
                        inputBufferEnd = 0;
                    }
                }
            }
        }
Пример #2
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if ((offset < 0) || (count < 0))
            {
                throw new ArgumentOutOfRangeException((offset < 0) ? nameof(offset) : nameof(count));
            }

            if (buffer.Length - offset < count)
            {
                throw new ArgumentException(Resources.InvalidOffsetCountLength);
            }

            // can't make progress without input...
            if (count == 0)
            {
                return;
            }

            // keep track of the number of bytes we've "written"
            _inputTotal += count;

            int inputUsed;
            int outputUsed;

            while (true)
            {
                if (_inputBufferEnd == 0)
                {
                    // there is no data in the inputBuffer, we can convert directly from the supplied
                    // buffer..

                    while (true)
                    {
                        var result = _encoder.Convert(buffer, offset, count,
                                                      _outputBuffer, 0, _outputBuffer.Length,
                                                      false,
                                                      out inputUsed,
                                                      out outputUsed);

                        // write any output that was produced..
                        if (outputUsed > 0)
                        {
                            _outputWriter.Write(_outputBuffer, 0, outputUsed);
                        }

                        // adjust counters..
                        offset += inputUsed;
                        if ((count -= inputUsed) == 0)
                        {
                            return;
                        }

                        // if we need more input to continue, then we're done..
                        if (result == ConvertStatus.InputRequired)
                        {
                            break;
                        }
                    }

                    // if we reach this code, there is unused data in buffer that we need to save
                    // for the next call to Write(). For all of the current BaseXX converters, this
                    // should never happen.

                    System.Diagnostics.Debug.Assert(count < _inputBufferLength);

                    if (_inputBuffer == null)
                    {
                        _inputBuffer = new byte[_inputBufferLength];
                    }

                    System.Diagnostics.Debug.Assert(_inputBufferEnd == 0);
                    Buffer.BlockCopy(buffer, offset, _inputBuffer, _inputBufferEnd, count);
                    _inputBufferEnd += count;

                    // no more data will be handled..
                    return;
                }
                else
                {
                    // we have existing data in the inputBuffer, add incoming data to the end
                    // and try to convert. The goal is to get out of this loop and return to
                    // converting directly from the buffer parameter.

                    int inputBufferOffset = 0;
                    int bytesToCopy       = Math.Min(count, _inputBuffer.Length - _inputBufferEnd);
                    System.Diagnostics.Debug.Assert(bytesToCopy > 0);

                    // copy data from buffer to inputBuffer and adjust offset/count values..
                    Buffer.BlockCopy(buffer, offset, _inputBuffer, _inputBufferEnd, bytesToCopy);
                    _inputBufferEnd += bytesToCopy;

                    while (true)
                    {
                        var result = _encoder.Convert(_inputBuffer, inputBufferOffset, _inputBufferEnd - inputBufferOffset,
                                                      _outputBuffer, 0, _outputBuffer.Length,
                                                      false,
                                                      out inputUsed,
                                                      out outputUsed);

                        if (outputUsed > 0)
                        {
                            _outputWriter.Write(_outputBuffer, 0, outputUsed);
                        }

                        inputBufferOffset += inputUsed;
                        if (result == ConvertStatus.InputRequired)
                        {
                            // encoder needs more input, if we've processed enough of the inputBuffer to overlap
                            // the incoming buffer then we want to switch to the other encoding loop.. no point in
                            // copying data if we don't have to.

                            if (inputBufferOffset >= _inputBufferEnd - bytesToCopy)
                            {
                                int bytesUsed = inputBufferOffset - (_inputBufferEnd - bytesToCopy);

                                // reset inputBuffer and adjust offset, if count is zero after adjustment just
                                // return (we've handled all of the input)

                                _inputBufferEnd = 0;
                                offset         += bytesUsed;
                                if ((count -= bytesUsed) == 0)
                                {
                                    return;
                                }

                                break;
                            }

                            // we didn't process enough input to overlap the incoming buffer, we have to make
                            // room in our inputBuffer for new data and keep trying..

                            Buffer.BlockCopy(_inputBuffer, inputBufferOffset, _inputBuffer, 0, _inputBufferEnd - inputBufferOffset);
                            _inputBufferEnd  -= inputBufferOffset;
                            inputBufferOffset = 0;

                            // copy new data into the buffer.. we have to update bytesToCopy as well to ensure that
                            // we keep track of where the incoming buffer overlaps the inputBuffer.

                            int newBytesToCopy = Math.Min(count - bytesToCopy, _inputBuffer.Length - _inputBufferEnd);
                            if (newBytesToCopy == 0)
                            {
                                return;
                            }

                            Buffer.BlockCopy(buffer, offset + bytesToCopy, _inputBuffer, _inputBufferEnd, newBytesToCopy);
                            _inputBufferEnd += newBytesToCopy;
                            bytesToCopy     += newBytesToCopy;
                        }
                    }
                }
            }
        }