]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Add a message reader. It's a tiny bit wonk, but it works
authorForest <chocozilla@gmail.com>
Fri, 20 Jul 2018 02:08:19 +0000 (19:08 -0700)
committerForest <chocozilla@gmail.com>
Fri, 20 Jul 2018 02:08:19 +0000 (19:08 -0700)
Hazel.UnitTests/Hazel.UnitTests.csproj
Hazel.UnitTests/MessageReaderTests.cs [new file with mode: 0644]
Hazel/BinaryReaderExtensions.cs [deleted file]
Hazel/Hazel.csproj
Hazel/MessageReader.cs [new file with mode: 0644]
Hazel/MessageWriter.cs

index b14bdd5e145a5a43cd779aba6352e7f27e60bdd0..4cd3d363993f79dbf2c0629dd56347fa0b2a9726 100644 (file)
@@ -26,6 +26,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -54,6 +55,7 @@
   </Choose>
   <ItemGroup>
     <Compile Include="BroadcastTests.cs" />
+    <Compile Include="MessageReaderTests.cs" />
     <Compile Include="StatisticsTests.cs" />
     <Compile Include="TestHelper.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/Hazel.UnitTests/MessageReaderTests.cs b/Hazel.UnitTests/MessageReaderTests.cs
new file mode 100644 (file)
index 0000000..80f54eb
--- /dev/null
@@ -0,0 +1,119 @@
+using System;
+using System.IO;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Hazel.UnitTests
+{
+    [TestClass]
+    public class MessageReaderTests
+    {
+        [TestMethod]
+        public void ReadProperInt()
+        {
+            const int Test1 = int.MaxValue;
+            const int Test2 = int.MinValue;
+
+            var msg = new MessageWriter(128);
+            msg.StartMessage(1);
+            msg.Write(Test1);
+            msg.Write(Test2);
+            msg.EndMessage();
+
+            Assert.AreEqual(11, msg.Length);
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            MessageReader reader = MessageReader.Get(msg.Buffer, 0);
+            Assert.AreEqual(Test1, reader.ReadInt32());
+            Assert.AreEqual(Test2, reader.ReadInt32());
+        }
+
+        [TestMethod]
+        public void ReadProperBool()
+        {
+            const bool Test1 = true;
+            const bool Test2 = false;
+
+            var msg = new MessageWriter(128);
+            msg.StartMessage(1);
+            msg.Write(Test1);
+            msg.Write(Test2);
+            msg.EndMessage();
+
+            Assert.AreEqual(5, msg.Length);
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            MessageReader reader = MessageReader.Get(msg.Buffer, 0);
+
+            Assert.AreEqual(Test1, reader.ReadBoolean());
+            Assert.AreEqual(Test2, reader.ReadBoolean());
+
+        }
+
+        [TestMethod]
+        public void ReadProperString()
+        {
+            const string Test1 = "Hello";
+            string Test2 = new string(' ', 1024);
+            var msg = new MessageWriter(2048);
+            msg.StartMessage(1);
+            msg.Write(Test1);
+            msg.Write(Test2);
+            msg.EndMessage();
+
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            MessageReader reader = MessageReader.Get(msg.Buffer, 0);
+
+            Assert.AreEqual(Test1, reader.ReadString());
+            Assert.AreEqual(Test2, reader.ReadString());
+
+        }
+
+        [TestMethod]
+        public void ReadProperFloat()
+        {
+            const float Test1 = 12.34f;
+
+            var msg = new MessageWriter(2048);
+            msg.StartMessage(1);
+            msg.Write(Test1);
+            msg.EndMessage();
+
+            Assert.AreEqual(7, msg.Length);
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            MessageReader reader = MessageReader.Get(msg.Buffer, 0);
+
+            Assert.AreEqual(Test1, reader.ReadSingle());
+
+        }
+
+        [TestMethod]
+        public void ReadMessageLength()
+        {
+            var msg = new MessageWriter(2048);
+            msg.StartMessage(1);
+            msg.Write(65534);
+            msg.StartMessage(2);
+            msg.Write("HO");
+            msg.EndMessage();
+            msg.EndMessage();
+
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            MessageReader reader = MessageReader.Get(msg.Buffer, 0);
+            Assert.AreEqual(1, reader.Tag);
+            Assert.AreEqual(65534, reader.ReadInt32()); // Content
+            var sub = reader.ReadMessage();
+            Assert.AreEqual(2, sub.Tag);
+            Assert.AreEqual("HO", sub.ReadString());
+
+        }
+
+        [TestMethod]
+        public void GetLittleEndian()
+        {
+            Assert.IsTrue(MessageWriter.IsLittleEndian());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Hazel/BinaryReaderExtensions.cs b/Hazel/BinaryReaderExtensions.cs
deleted file mode 100644 (file)
index 332f236..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.IO;
-
-namespace Hazel
-{
-    ///
-    public static class BinaryReaderExtensions
-    {
-        ///
-        public static uint ReadPackedUInt32(this BinaryReader reader)
-        {
-            bool readMore = true;
-            int shift = 0;
-            uint output = 0;
-
-            while (readMore)
-            {
-                byte b = reader.ReadByte();
-                if (b >= 0x80)
-                {
-                    readMore = true;
-                    b ^= 0x80;
-                }
-                else
-                {
-                    readMore = false;
-                }
-
-                output |= (uint)(b << shift);
-                shift += 7;
-            }
-
-            return output;
-        }
-
-        ///
-        public static int ReadPackedInt32(this BinaryReader reader)
-        {
-            return (int)reader.ReadPackedUInt32();
-        }
-
-        ///
-        public static byte[] ReadBytesAndSize(this BinaryReader reader)
-        {
-            int len = (int)reader.ReadPackedUInt32();
-            return reader.ReadBytes(len);
-        }
-    }
-}
\ No newline at end of file
index 1172bb03a70d7bcc55ff6cc51d586bb8010e1c1b..236a7b109db7cf6b891e13536e1f30b77c3ebe48 100644 (file)
@@ -32,7 +32,8 @@
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Hazel.XML</DocumentationFile>
+    <DocumentationFile>
+    </DocumentationFile>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup>
@@ -51,7 +52,6 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="BinaryReaderExtensions.cs" />
     <Compile Include="Connection.cs" />
     <Compile Include="ConnectionEndPoint.cs" />
     <Compile Include="ConnectionListener.cs" />
@@ -61,6 +61,7 @@
     <Compile Include="HazelException.cs" />
     <Compile Include="IPMode.cs" />
     <Compile Include="IRecyclable.cs" />
+    <Compile Include="MessageReader.cs" />
     <Compile Include="NetworkConnection.cs" />
     <Compile Include="NetworkConnectionListener.cs" />
     <Compile Include="NetworkEndPoint.cs" />
diff --git a/Hazel/MessageReader.cs b/Hazel/MessageReader.cs
new file mode 100644 (file)
index 0000000..7e4fc03
--- /dev/null
@@ -0,0 +1,176 @@
+using System;
+using System.Text;
+
+namespace Hazel
+{
+    ///
+    public class MessageReader : IRecyclable
+    {
+        private static readonly ObjectPool<MessageReader> objectPool = new ObjectPool<MessageReader>(() => new MessageReader());
+
+        private byte[] Buffer;
+        public byte Tag;
+        public int End;
+
+        public int Position;
+
+        public static MessageReader Get(byte[] buffer, int offset, int length)
+        {
+            var output = objectPool.GetObject();
+            output.Buffer = buffer;
+            output.Position = offset;
+            output.End = length + offset;
+            output.Tag = output.ReadByte();
+
+            return output;
+        }
+
+        public static MessageReader Get(byte[] buffer, int offset)
+        {
+            var output = objectPool.GetObject();
+            output.Buffer = buffer;
+            output.Position = offset;
+            output.End = output.ReadUInt16() + offset;
+            output.Tag = output.ReadByte();
+
+            return output;
+        }
+
+        ///
+        public MessageReader ReadMessage()
+        {
+            var output = MessageReader.Get(this.Buffer, this.Position);
+            this.Position += output.End;
+            return output;
+        }
+
+        ///
+        public void Recycle()
+        {
+            this.Position = this.End = 0;
+            objectPool.PutObject(this);
+        }
+
+        #region Read Methods
+        public bool ReadBoolean()
+        {
+            byte val = this.Buffer[this.Position++];
+            return val != 0;
+        }
+
+        public sbyte ReadSByte()
+        {
+            return (sbyte)this.Buffer[this.Position++];
+        }
+
+        public byte ReadByte()
+        {
+            return this.Buffer[this.Position++];
+        }
+
+        public ushort ReadUInt16()
+        {
+            ushort output = 
+                (ushort)(this.Buffer[Position++]
+                | this.Buffer[Position++] << 8);
+            return output;
+        }
+
+        public int ReadInt32()
+        {
+            int output = this.Buffer[Position++]
+                | this.Buffer[Position++] << 8
+                | this.Buffer[Position++] << 16
+                | this.Buffer[Position++] << 24;
+
+            return output;
+        }
+
+        public unsafe float ReadSingle()
+        {
+            float output = 0;
+            fixed (byte* bufPtr = &this.Buffer[this.Position])
+            {
+                byte* outPtr = (byte*)&output;
+
+                *outPtr = *bufPtr;
+                *(outPtr + 1) = *(bufPtr + 1);
+                *(outPtr + 2) = *(bufPtr + 2);
+                *(outPtr + 3) = *(bufPtr + 3);
+            }
+
+            this.Position += 4;
+            return output;
+        }
+
+        public string ReadString()
+        {
+            int len = this.ReadPackedInt32();
+            string output = UTF8Encoding.UTF8.GetString(this.Buffer, this.Position, len);
+
+            this.Position += len;
+            return output;
+        }
+
+        public byte[] ReadBytesAndSize()
+        {
+            int len = this.ReadPackedInt32();
+            return this.ReadBytes(len);
+        }
+
+        public byte[] ReadBytes(int length)
+        {
+            byte[] output = new byte[length];
+            Array.Copy(this.Buffer, this.Position, output, 0, output.Length);
+            this.Position += output.Length;
+            return output;
+        }
+
+        ///
+        public int ReadPackedInt32()
+        {
+            return (int)this.ReadPackedUInt32();
+        }
+
+        ///
+        public uint ReadPackedUInt32()
+        {
+            bool readMore = true;
+            int shift = 0;
+            uint output = 0;
+
+            while (readMore)
+            {
+                byte b = this.ReadByte();
+                if (b >= 0x80)
+                {
+                    readMore = true;
+                    b ^= 0x80;
+                }
+                else
+                {
+                    readMore = false;
+                }
+
+                output |= (uint)(b << shift);
+                shift += 7;
+            }
+
+            return output;
+        }
+        #endregion
+
+        public unsafe static bool IsLittleEndian()
+        {
+            byte b;
+            unsafe
+            {
+                int i = 1;
+                byte* bp = (byte*)&i;
+                b = *bp;
+            }
+
+            return b == 1;
+        }
+    }
+}
index 3508688ee9c6b1620f698ee96b08245018167a53..22640e6ac490b81d6ceacdc78404773948ca8fe6 100644 (file)
@@ -101,13 +101,19 @@ namespace Hazel
             if (this.Position > this.Length) this.Length = this.Position;
         }
 
+        public void Write(sbyte value)
+        {
+            this.Buffer[this.Position++] = (byte)value;
+            if (this.Position > this.Length) this.Length = this.Position;
+        }
+
         public void Write(byte value)
         {
             this.Buffer[this.Position++] = value;
             if (this.Position > this.Length) this.Length = this.Position;
         }
 
-        public void Write(short value)
+        public void Write(ushort value)
         {
             this.Buffer[this.Position++] = (byte)value;
             this.Buffer[this.Position++] = (byte)(value >> 8);