diff --git a/Lidgren.Network/NetIncomingMessage.Read.cs b/Lidgren.Network/NetIncomingMessage.Read.cs index 1432e53..5eb0b2f 100644 --- a/Lidgren.Network/NetIncomingMessage.Read.cs +++ b/Lidgren.Network/NetIncomingMessage.Read.cs @@ -90,7 +90,22 @@ namespace Lidgren.Network m_readPosition += 8; return retval; } - + + /// + /// Reads a byte and returns true or false for success + /// + public bool ReadByte(out byte result) + { + if (m_bitLength - m_readPosition < 8) + { + result = 0; + return false; + } + result = NetBitWriter.ReadByte(m_data, 8, m_readPosition); + m_readPosition += 8; + return true; + } + /// /// Reads a signed byte /// @@ -127,6 +142,23 @@ namespace Lidgren.Network return retval; } + /// + /// Reads the specified number of bytes and returns true for success + /// + public bool ReadBytes(int numberOfBytes, out byte[] result) + { + if (m_bitLength - m_readPosition + 7 < (numberOfBytes * 8)) + { + result = null; + return false; + } + + result = new byte[numberOfBytes]; + NetBitWriter.ReadBytes(m_data, numberOfBytes, m_readPosition, result, 0); + m_readPosition += (8 * numberOfBytes); + return true; + } + /// /// Reads the specified number of bytes into a preallocated array /// @@ -239,6 +271,22 @@ namespace Lidgren.Network return retval; } + /// + /// Reads an 32 bit unsigned integer written using Write(UInt32) and returns true for success + /// + [CLSCompliant(false)] + public bool ReadUInt32(out UInt32 result) + { + if (m_bitLength - m_readPosition < 32) + { + result = 0; + return false; + } + result = NetBitWriter.ReadUInt32(m_data, 32, m_readPosition); + m_readPosition += 32; + return true; + } + /// /// Reads an unsigned integer stored in 1 to 32 bits, written using Write(UInt32, Int32) /// @@ -384,6 +432,32 @@ namespace Lidgren.Network } } + /// + /// Reads a variable sized UInt32 written using WriteVariableUInt32() and returns true for success + /// + [CLSCompliant(false)] + public bool ReadVariableUInt32(out uint result) + { + int num1 = 0; + int num2 = 0; + while (true) + { + byte num3; + if (ReadByte(out num3) == false) + { + result = 0; + return false; + } + num1 |= (num3 & 0x7f) << num2; + num2 += 7; + if ((num3 & 0x80) == 0) + { + result = (uint)num1; + return true; + } + } + } + /// /// Reads a variable sized Int32 written using WriteVariableInt32() /// @@ -502,6 +576,49 @@ namespace Lidgren.Network return System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length); } + /// + /// Reads a string written using Write(string) and returns true for success + /// + public bool ReadString(out string result) + { + uint byteLen; + if (ReadVariableUInt32(out byteLen) == false) + { + result = String.Empty; + return false; + } + + if (byteLen == 0) + { + result = String.Empty; + return true; + } + + if (m_bitLength - m_readPosition < (byteLen * 8)) + { + result = String.Empty; + return false; + } + + if ((m_readPosition & 7) == 0) + { + // read directly + result = System.Text.Encoding.UTF8.GetString(m_data, m_readPosition >> 3, (int)byteLen); + m_readPosition += (8 * (int)byteLen); + return true; + } + + byte[] bytes; + if (ReadBytes((int)byteLen, out bytes) == false) + { + result = String.Empty; + return false; + } + + result = System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length); + return true; + } + /// /// Reads a stored IPv4 endpoint description /// diff --git a/UnitTests/ReadWriteTests.cs b/UnitTests/ReadWriteTests.cs index 0327d71..cec9961 100644 --- a/UnitTests/ReadWriteTests.cs +++ b/UnitTests/ReadWriteTests.cs @@ -69,7 +69,13 @@ namespace UnitTests bdr.Append(inc.ReadBoolean()); bdr.Append(inc.ReadInt32(6)); bdr.Append(inc.ReadInt32()); - bdr.Append(inc.ReadString()); + + string strResult; + bool ok = inc.ReadString(out strResult); + if (ok == false) + throw new NetException("Read/write failure"); + bdr.Append(strResult); + bdr.Append(inc.ReadByte()); if (inc.PeekUInt16() != (ushort)44)