public void ReadMessage()

in FixAntenna/NetCore/FixEngine/Transport/NewMessageChopper.cs [126:346]


		public void ReadMessage(MsgBuf buf)
		{

			var message = buf.FixMessage;
			if (message == null)
			{
				message = new FixMessage();
				buf.FixMessage = message;
			}

			if (_parsedOffset == _readOffset)
			{
				_parsedOffset = _readOffset = 0; // no data left in buffer, roll back to the beginning
			}
			else
			{
				if (_readOffset > SocketReadSize / 2)
				{
					var availData = _readOffset - _parsedOffset;
					var tail = SocketReadSize - _readOffset;

					if (availData < 256 || tail < 1024) // preventive data move ?
					{
						Array.Copy(_buffer, _parsedOffset, _buffer, 0, availData);
						_readOffset -= _parsedOffset;
						_parsedOffset = 0;
					}
				}
			}

			_messageStartOffset = _parsedOffset;

			while (_parsedOffset + 20 > _readOffset)
			{
				ReadAvailableBytesToBuffer(buf);
			}


			message.SetBuffer(_buffer, _messageStartOffset, _readOffset);

			var valueStartIndex = 0;
			var tag = 0;
			var isTagParsing = true;
			var readSomeBytes = false;

			var userStopParse = false;
			var isHeaderTag = true;
			var isAdminMsg = false;
			var stopParse = false;

			OnMessageStart();
			while (true)
			{

				while (_parsedOffset >= _readOffset)
				{
					ReadAvailableBytesToBuffer(buf);
					readSomeBytes = true;
				}

				if (readSomeBytes)
				{
					readSomeBytes = false;

					if (_readOffset <= SocketReadSize || _messageStartOffset == 0)
					{
						message.SetBuffer(_buffer, _messageStartOffset, _readOffset);
					}
					else
					{
						// end of buffer reached, wrap around now and move remaining data to buffer's head
						Array.Copy(_buffer, _messageStartOffset, _buffer, 0, _readOffset - _messageStartOffset);
						_readOffset -= _messageStartOffset;
						_parsedOffset -= _messageStartOffset;
						valueStartIndex -= _messageStartOffset;
						_messageStartOffset = 0;

						message.ShiftBuffer(_buffer, _messageStartOffset, _readOffset);
					}
				}

				var b = _buffer[_parsedOffset];

				if (isTagParsing)
				{
					if (b >= (byte)'0' && b <= (byte)'9')
					{
						tag = tag * 10 + (b - '0');
					}
					else if (b == (byte)'=')
					{
						if (RawTags.IsWithinRawTags(tag))
						{
							var rawLength = 0;
							if (message.IsMessageIncomplete)
							{
								byte bv;
								for (var i = valueStartIndex; i < _parsedOffset; i++)
								{
									bv = _buffer[i];
									if (bv >= (byte)'0' && bv <= (byte)'9')
									{
										rawLength = rawLength * 10 + (bv - '0');
									}
									else
									{
										break;
									}
								}
							}
							else
							{
								rawLength = RawFixUtil.GetRawTagLengthFromPreviousField(message);
							}
							if (rawLength > _maxMessageSize)
							{
								throw new GarbledMessageException(MessageChopperFields.RawDataLengthIsTooBigError + " (" + rawLength + ")");
							}
							valueStartIndex = _parsedOffset + 1;
							_parsedOffset += rawLength;
						}
						else
						{
							valueStartIndex = _parsedOffset + 1;
						}
						isTagParsing = false;
					}
					else
					{
						GetMessage(buf);
						throw new GarbledMessageException("Invalid tag number");
					}
				}
				else
				{
					if (b == (byte)'\x0001')
					{
						if (_isAdvancedParseControl)
						{
							if (userStopParse)
							{
								if (isHeaderTag)
								{
									if (ParseRequiredTags.IsHeader(tag))
									{
										message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
									}
									else
									{
										message.LoadTagValue(35, _tempValue);
										isAdminMsg = ParseRequiredTags.IsAdminMsg(_tempValue);
										isHeaderTag = false;
										if (isAdminMsg)
										{
											message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
										}
									}
								}
								else if (isAdminMsg)
								{
									message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
								}
								else if (!stopParse)
								{
									// can be stop
									message.LoadTagValue(9, _tempValue);
									var msgLength = (int) _tempValue.LongValue;
									//            | length considered from this point      |  length   |
									_parsedOffset = _tempValue.Offset + _tempValue.Length + 1 + msgLength - 1;
									stopParse = true;
								}
								else if (tag == 10)
								{
									message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
								}
							}
							else
							{
								var control = _parserListener.OnTag(tag, _buffer, valueStartIndex, _parsedOffset - valueStartIndex);
								if (control == FixParserListenerParseControl.Continue)
								{
									message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
								}
								else
								{
									// IGNORE or STOP
									if (ParseRequiredTags.IsRequired(tag))
									{
										message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
									}
									else
									{
										message.IsMessageIncomplete = true;
									}
									if (control == FixParserListenerParseControl.StopParse)
									{
										userStopParse = true;
									}
								}
							}
						}
						else
						{
							message.Add(tag, valueStartIndex, _parsedOffset - valueStartIndex);
						}
						if (tag == 10)
						{
							_parsedOffset++;
							message.SetBuffer(_buffer, _messageStartOffset, _parsedOffset - _messageStartOffset);
							break;
						}
						tag = 0;
						isTagParsing = true;
					}
				}
				_parsedOffset++;
			}

			OnMessageEnd();
			GetMessage(buf);
		}