Thrift now a TLP - INFRA-3116

git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.1.x@1028168 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/csharp/src/Protocol/TBinaryProtocol.cs b/lib/csharp/src/Protocol/TBinaryProtocol.cs
new file mode 100644
index 0000000..14ca43b
--- /dev/null
+++ b/lib/csharp/src/Protocol/TBinaryProtocol.cs
@@ -0,0 +1,392 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+
+namespace Thrift.Protocol
+{
+	public class TBinaryProtocol : TProtocol
+	{
+		protected const uint VERSION_MASK = 0xffff0000;
+		protected const uint VERSION_1 = 0x80010000;
+
+		protected bool strictRead_ = false;
+		protected bool strictWrite_ = true;
+
+		protected int readLength_;
+		protected bool checkReadLength_ = false;
+
+
+		#region BinaryProtocol Factory
+		 /**
+		  * Factory
+		  */
+		  public class Factory : TProtocolFactory {
+
+			  protected bool strictRead_ = false;
+			  protected bool strictWrite_ = true;
+
+			  public Factory()
+				  :this(false, true)
+			  {
+			  }
+
+			  public Factory(bool strictRead, bool strictWrite)
+			  {
+				  strictRead_ = strictRead;
+				  strictWrite_ = strictWrite;
+			  }
+
+			public TProtocol GetProtocol(TTransport trans) {
+			  return new TBinaryProtocol(trans, strictRead_, strictWrite_);
+			}
+		  }
+
+		#endregion
+
+		public TBinaryProtocol(TTransport trans)
+			: this(trans, false, true)
+		{
+		}
+
+		public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
+			:base(trans)
+		{
+			strictRead_ = strictRead;
+			strictWrite_ = strictWrite;
+		}
+
+		#region Write Methods
+
+		public override void WriteMessageBegin(TMessage message)
+		{
+			if (strictWrite_)
+			{
+				uint version = VERSION_1 | (uint)(message.Type);
+				WriteI32((int)version);
+				WriteString(message.Name);
+				WriteI32(message.SeqID);
+			}
+			else
+			{
+				WriteString(message.Name);
+				WriteByte((byte)message.Type);
+				WriteI32(message.SeqID);
+			}
+		}
+
+		public override void WriteMessageEnd()
+		{
+		}
+
+		public override void WriteStructBegin(TStruct struc)
+		{
+		}
+
+		public override void WriteStructEnd()
+		{
+		}
+
+		public override void WriteFieldBegin(TField field)
+		{
+			WriteByte((byte)field.Type);
+			WriteI16(field.ID);
+		}
+
+		public override void WriteFieldEnd()
+		{
+		}
+
+		public override void WriteFieldStop()
+		{
+			WriteByte((byte)TType.Stop);
+		}
+
+		public override void WriteMapBegin(TMap map)
+		{
+			WriteByte((byte)map.KeyType);
+			WriteByte((byte)map.ValueType);
+			WriteI32(map.Count);
+		}
+
+		public override void WriteMapEnd()
+		{
+		}
+
+		public override void WriteListBegin(TList list)
+		{
+			WriteByte((byte)list.ElementType);
+			WriteI32(list.Count);
+		}
+
+		public override void WriteListEnd()
+		{
+		}
+
+		public override void WriteSetBegin(TSet set)
+		{
+			WriteByte((byte)set.ElementType);
+			WriteI32(set.Count);
+		}
+
+		public override void WriteSetEnd()
+		{
+		}
+
+		public override void WriteBool(bool b)
+		{
+			WriteByte(b ? (byte)1 : (byte)0);
+		}
+
+		private byte[] bout = new byte[1];
+		public override void WriteByte(byte b)
+		{
+			bout[0] = b;
+			trans.Write(bout, 0, 1);
+		}
+
+		private byte[] i16out = new byte[2];
+		public override void WriteI16(short s)
+		{
+			i16out[0] = (byte)(0xff & (s >> 8));
+			i16out[1] = (byte)(0xff & s);
+			trans.Write(i16out, 0, 2);
+		}
+
+		private byte[] i32out = new byte[4];
+		public override void WriteI32(int i32)
+		{
+			i32out[0] = (byte)(0xff & (i32 >> 24));
+			i32out[1] = (byte)(0xff & (i32 >> 16));
+			i32out[2] = (byte)(0xff & (i32 >> 8));
+			i32out[3] = (byte)(0xff & i32);
+			trans.Write(i32out, 0, 4);
+		}
+
+		private byte[] i64out = new byte[8];
+		public override void WriteI64(long i64)
+		{
+			i64out[0] = (byte)(0xff & (i64 >> 56));
+			i64out[1] = (byte)(0xff & (i64 >> 48));
+			i64out[2] = (byte)(0xff & (i64 >> 40));
+			i64out[3] = (byte)(0xff & (i64 >> 32));
+			i64out[4] = (byte)(0xff & (i64 >> 24));
+			i64out[5] = (byte)(0xff & (i64 >> 16));
+			i64out[6] = (byte)(0xff & (i64 >> 8));
+			i64out[7] = (byte)(0xff & i64);
+			trans.Write(i64out, 0, 8);
+		}
+
+		public override void WriteDouble(double d)
+		{
+			WriteI64(BitConverter.DoubleToInt64Bits(d));
+		}
+
+		public override void WriteBinary(byte[] b)
+		{
+			WriteI32(b.Length);
+			trans.Write(b, 0, b.Length);
+		}
+
+		#endregion
+
+		#region ReadMethods
+
+		public override TMessage ReadMessageBegin()
+		{
+			TMessage message = new TMessage();
+			int size = ReadI32();
+			if (size < 0)
+			{
+				uint version = (uint)size & VERSION_MASK;
+				if (version != VERSION_1)
+				{
+					throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
+				}
+				message.Type = (TMessageType)(size & 0x000000ff);
+				message.Name = ReadString();
+				message.SeqID = ReadI32();
+			}
+			else
+			{
+				if (strictRead_)
+				{
+					throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
+				}
+				message.Name = ReadStringBody(size);
+				message.Type = (TMessageType)ReadByte();
+				message.SeqID = ReadI32();
+			}
+			return message;
+		}
+
+		public override void ReadMessageEnd()
+		{
+		}
+
+		public override TStruct ReadStructBegin()
+		{
+			return new TStruct();
+		}
+
+		public override void ReadStructEnd()
+		{
+		}
+
+		public override TField ReadFieldBegin()
+		{
+			TField field = new TField();
+			field.Type = (TType)ReadByte();
+
+			if (field.Type != TType.Stop)
+			{
+				field.ID = ReadI16();
+			}
+
+			return field;
+		}
+
+		public override void ReadFieldEnd()
+		{
+		}
+
+		public override TMap ReadMapBegin()
+		{
+			TMap map = new TMap();
+			map.KeyType = (TType)ReadByte();
+			map.ValueType = (TType)ReadByte();
+			map.Count = ReadI32();
+
+			return map;
+		}
+
+		public override void ReadMapEnd()
+		{
+		}
+
+		public override TList ReadListBegin()
+		{
+			TList list = new TList();
+			list.ElementType = (TType)ReadByte();
+			list.Count = ReadI32();
+
+			return list;
+		}
+
+		public override void ReadListEnd()
+		{
+		}
+
+		public override TSet ReadSetBegin()
+		{
+			TSet set = new TSet();
+			set.ElementType = (TType)ReadByte();
+			set.Count = ReadI32();
+
+			return set;
+		}
+
+		public override void ReadSetEnd()
+		{
+		}
+
+		public override bool ReadBool()
+		{
+			return ReadByte() == 1;
+		}
+
+		private byte[] bin = new byte[1];
+		public override byte ReadByte()
+		{
+			ReadAll(bin, 0, 1);
+			return bin[0];
+		}
+
+		private byte[] i16in = new byte[2];
+		public override short ReadI16()
+		{
+			ReadAll(i16in, 0, 2);
+			return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
+		}
+
+		private byte[] i32in = new byte[4];
+		public override int ReadI32()
+		{
+			ReadAll(i32in, 0, 4);
+			return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
+		}
+
+		private byte[] i64in = new byte[8];
+		public override long ReadI64()
+		{
+			ReadAll(i64in, 0, 8);
+			return (long)(((long)(i64in[0] & 0xff) << 56) | ((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[3] & 0xff) << 32) |
+				((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[7] & 0xff)));
+		}
+
+		public override double ReadDouble()
+		{
+			return BitConverter.Int64BitsToDouble(ReadI64());
+		}
+
+		public void SetReadLength(int readLength)
+		{
+			readLength_ = readLength;
+			checkReadLength_ = true;
+		}
+
+		protected void CheckReadLength(int length)
+		{
+			if (checkReadLength_)
+			{
+				readLength_ -= length;
+				if (readLength_ < 0)
+				{
+					throw new Exception("Message length exceeded: " + length);
+				}
+			}
+		}
+
+		public override byte[] ReadBinary()
+		{
+			int size = ReadI32();
+			CheckReadLength(size);
+			byte[] buf = new byte[size];
+			trans.ReadAll(buf, 0, size);
+			return buf;
+		}
+		private  string ReadStringBody(int size)
+		{
+			CheckReadLength(size);
+			byte[] buf = new byte[size];
+			trans.ReadAll(buf, 0, size);
+			return Encoding.UTF8.GetString(buf);
+		}
+
+		private int ReadAll(byte[] buf, int off, int len)
+		{
+			CheckReadLength(len);
+			return trans.ReadAll(buf, off, len);
+		}
+
+		#endregion
+	}
+}