public void Reset(IRequestInfo requestInfo) {
     _requestInfo = requestInfo;
     _carriageReturn = false;
     _statusBuffer.Length = 0;
     _bufferPosition = 0;
     _bufferDataLength = 0;
     _responseDataPosition = 0;
     _currentResponse = new Response(new[] { "ERROR", "INCOMPLETE" });
 }
        private void ProcessCommandData() {
            while(true) {

                // look for \r\n
                for(var i = 0; i < _bufferDataLength; i++) {
                    var idx = _bufferPosition + i;

                    if(_buffer[idx] == '\r') {
                        _carriageReturn = true;
                    } else if(_carriageReturn) {
                        if(_buffer[idx] != '\n') {

                            // it wasn't a \r followed by an \n
                            var receivedCommandData = Encoding.ASCII.GetString(_buffer, _bufferPosition, i - 1);
                            throw new IncompleteCommandTerminator(receivedCommandData);
                        }
                        _carriageReturn = false;
                        var consumeLength = i - 1;
                        if(consumeLength > 0) {

                            // it is possible that this buffer pass is only the terminator or part of the terminator, so only
                            // read from it if there are non-terminator characters
                            _statusBuffer.Append(Encoding.ASCII.GetString(_buffer, _bufferPosition, consumeLength));
                        }
                        var status = _statusBuffer.ToString().Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                        _statusBuffer.Length = 0;
                        _currentResponse = new Response(status);
                        _responseExpectedBytes = _requestInfo.ExpectedBytes(_currentResponse);
                        _bufferPosition += (i + 1);
                        _bufferDataLength -= (i + 1);
                        if(_responseExpectedBytes >= 0) {
                            if(_bufferDataLength == 0) {
                                Receive();
                            }
                            _responseDataPosition = 0;
                            _responseData = new byte[_responseExpectedBytes];
                            ProcessPayloadData();
                        }

                        // at this point _currentResponse should be fully populated
                        return;
                    }
                }
                var length = _bufferDataLength;
                if(_carriageReturn) {

                    // we've found the \r, but the \n wasn't part of the buffer, so consume all but the last char from buffer
                    // since we never want to read the terminator into the status buffer
                    length--;
                    if(length < 0) {
                        return;
                    }
                }
                _statusBuffer.Append(Encoding.ASCII.GetString(_buffer, _bufferPosition, length));
                Receive();
            }
        }