diff Main/jungle-main/persistent/msgpack/src/CompiledPacker.cs @ 20:1f99e150f336

fix folder and add Object Mapper.
author Kazuma Takeda
date Thu, 15 Dec 2016 22:52:48 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Main/jungle-main/persistent/msgpack/src/CompiledPacker.cs	Thu Dec 15 22:52:48 2016 +0900
@@ -0,0 +1,549 @@
+//
+// Copyright 2011 Kazuki Oikawa
+//
+// Licensed 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.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Threading;
+using MsgPack.Compiler;
+
+namespace MsgPack
+{
+	public class CompiledPacker
+	{
+		static PackerBase _publicFieldPacker, _allFieldPacker;
+		PackerBase _packer;
+
+		static CompiledPacker ()
+		{
+			_publicFieldPacker = new MethodBuilderPacker ();
+			_allFieldPacker = new DynamicMethodPacker ();
+		}
+
+		public CompiledPacker () : this (false) {}
+		public CompiledPacker (bool packPrivateField)
+		{
+			_packer = (packPrivateField ? _allFieldPacker : _publicFieldPacker);
+		}
+
+		public void Prepare<T> ()
+		{
+			_packer.CreatePacker<T> ();
+			_packer.CreateUnpacker<T> ();
+		}
+
+		#region Generics Pack/Unpack Methods
+		public byte[] Pack<T> (T o)
+		{
+			using (MemoryStream ms = new MemoryStream ()) {
+				Pack<T> (ms, o);
+				return ms.ToArray ();
+			}
+		}
+
+		public void Pack<T> (Stream strm, T o)
+		{
+			_packer.CreatePacker<T> () (new MsgPackWriter (strm), o);
+		}
+
+		public T Unpack<T> (byte[] buf)
+		{
+			return Unpack<T> (buf, 0, buf.Length);
+		}
+
+		public T Unpack<T> (byte[] buf, int offset, int size)
+		{
+			using (MemoryStream ms = new MemoryStream (buf, offset, size)) {
+				return Unpack<T> (ms);
+			}
+		}
+
+		public T Unpack<T> (Stream strm)
+		{
+			return _packer.CreateUnpacker<T> () (new MsgPackReader (strm));
+		}
+		#endregion
+
+		#region Non-generics Pack/Unpack Methods
+		public byte[] Pack (object o)
+		{
+			using (MemoryStream ms = new MemoryStream ()) {
+				Pack (ms, o);
+				return ms.ToArray ();
+			}
+		}
+
+		public void Pack (Stream strm, object o)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public object Unpack (Type t, byte[] buf)
+		{
+			return Unpack (t, buf, 0, buf.Length);
+		}
+
+		public object Unpack (Type t, byte[] buf, int offset, int size)
+		{
+			using (MemoryStream ms = new MemoryStream (buf, offset, size)) {
+				return Unpack (t, ms);
+			}
+		}
+
+		public object Unpack (Type t, Stream strm)
+		{
+			throw new NotImplementedException ();
+		}
+		#endregion
+
+		#region Compiled Packer Implementations
+		public abstract class PackerBase
+		{
+			Dictionary<Type, Delegate> _packers = new Dictionary<Type, Delegate> ();
+			Dictionary<Type, Delegate> _unpackers = new Dictionary<Type, Delegate> ();
+
+			protected Dictionary<Type, MethodInfo> _packMethods = new Dictionary<Type, MethodInfo> ();
+			protected Dictionary<Type, MethodInfo> _unpackMethods = new Dictionary<Type, MethodInfo> ();
+
+			protected PackerBase ()
+			{
+				DefaultPackMethods.Register (_packMethods, _unpackMethods);
+			}
+
+			public Action<MsgPackWriter, T> CreatePacker<T> ()
+			{
+				Delegate d;
+				lock (_packers) {
+					if (!_packers.TryGetValue (typeof (T), out d)) {
+						d = CreatePacker_Internal<T> ();
+						_packers.Add (typeof (T), d);
+					}
+				}
+				return (Action<MsgPackWriter, T>)d;
+			}
+
+			public Func<MsgPackReader, T> CreateUnpacker<T> ()
+			{
+				Delegate d;
+				lock (_unpackers) {
+					if (!_unpackers.TryGetValue (typeof (T), out d)) {
+						d = CreateUnpacker_Internal<T> ();
+						_unpackers.Add (typeof (T), d);
+					}
+				}
+				return (Func<MsgPackReader, T>)d;
+			}
+
+			protected abstract Action<MsgPackWriter, T> CreatePacker_Internal<T> ();
+			protected abstract Func<MsgPackReader, T> CreateUnpacker_Internal<T> ();
+		}
+		public sealed class DynamicMethodPacker : PackerBase
+		{
+			 private static MethodInfo LookupMemberMappingMethod;
+			static Dictionary<Type, IDictionary<string, int>> UnpackMemberMappings;
+
+			static DynamicMethodPacker ()
+			{
+				UnpackMemberMappings = new Dictionary<Type, IDictionary<string, int>> ();
+				LookupMemberMappingMethod = typeof (DynamicMethodPacker).GetMethod ("LookupMemberMapping", BindingFlags.Static | BindingFlags.NonPublic);
+			}
+
+			public DynamicMethodPacker () : base ()
+			{
+			}
+
+			protected override Action<MsgPackWriter, T> CreatePacker_Internal<T> ()
+			{
+				DynamicMethod dm = CreatePacker (typeof (T), CreatePackDynamicMethod (typeof (T)));
+				return (Action<MsgPackWriter, T>)dm.CreateDelegate (typeof (Action<MsgPackWriter, T>));
+			}
+
+			protected override Func<MsgPackReader, T> CreateUnpacker_Internal<T> ()
+			{
+				DynamicMethod dm = CreateUnpacker (typeof (T), CreateUnpackDynamicMethod (typeof (T)));
+				return (Func<MsgPackReader, T>)dm.CreateDelegate (typeof (Func<MsgPackReader, T>));
+			}
+
+			DynamicMethod CreatePacker (Type t, DynamicMethod dm)
+			{
+				ILGenerator il = dm.GetILGenerator ();
+				_packMethods.Add (t, dm);
+				PackILGenerator.EmitPackCode (t, dm, il, LookupMembers, FormatMemberName, LookupPackMethod);
+				return dm;
+			}
+
+			DynamicMethod CreateUnpacker (Type t, DynamicMethod dm)
+			{
+				ILGenerator il = dm.GetILGenerator ();
+				_unpackMethods.Add (t, dm);
+				PackILGenerator.EmitUnpackCode (t, dm, il, LookupMembers, FormatMemberName, LookupUnpackMethod,
+					LookupMemberMapping, LookupMemberMappingMethod);
+				return dm;
+			}
+
+			static DynamicMethod CreatePackDynamicMethod (Type t)
+			{
+				return CreateDynamicMethod (typeof (void), new Type[] {typeof (MsgPackWriter), t});
+			}
+
+			static DynamicMethod CreateUnpackDynamicMethod (Type t)
+			{
+				return CreateDynamicMethod (t, new Type[] {typeof (MsgPackReader)});
+			}
+
+			static MemberInfo[] LookupMembers (Type t)
+			{
+				BindingFlags baseFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
+				System.Collections.Generic.List<MemberInfo> list = new System.Collections.Generic.List<MemberInfo> ();
+				list.AddRange (t.GetFields (baseFlags));
+				// TODO: Add NonSerialized Attribute Filter ?
+				return list.ToArray ();
+			}
+
+			MethodInfo LookupPackMethod (Type t)
+			{
+				MethodInfo mi;
+				DynamicMethod dm;
+				if (_packMethods.TryGetValue (t, out mi))
+					return mi;
+				dm = CreatePackDynamicMethod (t);
+				return CreatePacker (t, dm);
+			}
+
+			MethodInfo LookupUnpackMethod (Type t)
+			{
+				MethodInfo mi;
+				if (_unpackMethods.TryGetValue (t, out mi))
+					return mi;
+				DynamicMethod dm = CreateUnpackDynamicMethod (t);
+				return CreateUnpacker (t, dm);
+			}
+
+			static string FormatMemberName (MemberInfo m)
+			{
+				if (m.MemberType != MemberTypes.Field)
+					return m.Name;
+
+				int pos;
+				string name = m.Name;
+				if (name[0] == '<' && (pos = name.IndexOf ('>')) > 1)
+					name = name.Substring (1, pos - 1); // Auto-Property (\<.+\>) <ab>
+				return name;
+			}
+
+			static int _dynamicMethodIdx = 0;
+			static DynamicMethod CreateDynamicMethod (Type returnType, Type[] parameterTypes)
+			{
+				string name = "_" + Interlocked.Increment (ref _dynamicMethodIdx).ToString ();
+				return new DynamicMethod (name, returnType, parameterTypes, true);
+			}
+
+			internal static IDictionary<string,int> LookupMemberMapping (Type t)
+			{
+				IDictionary<string, int> mapping;
+				lock (UnpackMemberMappings) {
+					if (!UnpackMemberMappings.TryGetValue (t, out mapping)) {
+						mapping = new Dictionary<string, int> ();
+						UnpackMemberMappings.Add (t, mapping);
+					}
+				}
+				return mapping;
+			}
+		}
+		public sealed class MethodBuilderPacker : PackerBase
+		{
+			public const string AssemblyName = "MessagePackInternalAssembly";
+			static AssemblyName DynamicAsmName;
+			static AssemblyBuilder DynamicAsmBuilder;
+			static ModuleBuilder DynamicModuleBuilder;
+
+			private static MethodInfo LookupMemberMappingMethod;
+			static Dictionary<Type, IDictionary<string, int>> UnpackMemberMappings;
+
+			static MethodBuilderPacker ()
+			{
+				UnpackMemberMappings = new Dictionary<Type, IDictionary<string, int>> ();
+				LookupMemberMappingMethod = typeof (MethodBuilderPacker).GetMethod ("LookupMemberMapping", BindingFlags.Static | BindingFlags.NonPublic);
+
+				DynamicAsmName = new AssemblyName (AssemblyName);
+				DynamicAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (DynamicAsmName, AssemblyBuilderAccess.Run);
+				DynamicModuleBuilder = DynamicAsmBuilder.DefineDynamicModule (DynamicAsmName.Name);
+			}
+
+			public MethodBuilderPacker () : base ()
+			{
+			}
+
+			protected override Action<MsgPackWriter, T> CreatePacker_Internal<T> ()
+			{
+				TypeBuilder tb;
+				MethodBuilder mb;
+				CreatePackMethodBuilder (typeof (T), out tb, out mb);
+				_packMethods.Add (typeof (T), mb);
+				CreatePacker (typeof (T), mb);
+				MethodInfo mi = ToCallableMethodInfo (typeof (T), tb, true);
+				return (Action<MsgPackWriter, T>)Delegate.CreateDelegate (typeof (Action<MsgPackWriter, T>), mi);
+			}
+
+			protected override Func<MsgPackReader, T> CreateUnpacker_Internal<T> ()
+			{
+				TypeBuilder tb;
+				MethodBuilder mb;
+				CreateUnpackMethodBuilder (typeof (T), out tb, out mb);
+				_unpackMethods.Add (typeof (T), mb);
+				CreateUnpacker (typeof (T), mb);
+				MethodInfo mi = ToCallableMethodInfo (typeof (T), tb, false);
+				return (Func<MsgPackReader, T>)Delegate.CreateDelegate (typeof (Func<MsgPackReader, T>), mi);
+			}
+
+			void CreatePacker (Type t, MethodBuilder mb)
+			{
+				ILGenerator il = mb.GetILGenerator ();
+				PackILGenerator.EmitPackCode (t, mb, il, LookupMembers, FormatMemberName, LookupPackMethod);
+			}
+
+			void CreateUnpacker (Type t, MethodBuilder mb)
+			{
+				ILGenerator il = mb.GetILGenerator ();
+				PackILGenerator.EmitUnpackCode (t, mb, il, LookupMembers, FormatMemberName, LookupUnpackMethod,
+					LookupMemberMapping, LookupMemberMappingMethod);
+			}
+
+			MethodInfo ToCallableMethodInfo (Type t, TypeBuilder tb, bool isPacker)
+			{
+				Type type = tb.CreateType ();
+				MethodInfo mi = type.GetMethod (isPacker ? "Pack" : "Unpack", BindingFlags.Static | BindingFlags.Public);
+				if (isPacker) {
+					_packMethods[t] = mi;
+				} else {
+					_unpackMethods[t] = mi;
+				}
+				return mi;
+			}
+
+			MethodInfo LookupPackMethod (Type t)
+			{
+				MethodInfo mi;
+				TypeBuilder tb;
+				MethodBuilder mb;
+				if (_packMethods.TryGetValue (t, out mi))
+					return mi;
+				CreatePackMethodBuilder (t, out tb, out mb);
+				_packMethods.Add (t, mb);
+				CreatePacker (t, mb);
+				return ToCallableMethodInfo (t, tb, true);
+			}
+
+			MethodInfo LookupUnpackMethod (Type t)
+			{
+				MethodInfo mi;
+				TypeBuilder tb;
+				MethodBuilder mb;
+				if (_unpackMethods.TryGetValue (t, out mi))
+					return mi;
+				CreateUnpackMethodBuilder (t, out tb, out mb);
+				_unpackMethods.Add (t, mb);
+				CreateUnpacker (t, mb);
+				return ToCallableMethodInfo (t, tb, false);
+			}
+
+			static string FormatMemberName (MemberInfo m)
+			{
+				return m.Name;
+			}
+
+			static MemberInfo[] LookupMembers (Type t)
+			{
+				BindingFlags baseFlags = BindingFlags.Instance | BindingFlags.Public;
+				System.Collections.Generic.List<MemberInfo> list = new System.Collections.Generic.List<MemberInfo> ();
+				list.AddRange (t.GetFields (baseFlags));
+				// TODO: Add NonSerialized Attribute Filter ?
+				return list.ToArray ();
+			}
+
+			static void CreatePackMethodBuilder (Type t, out TypeBuilder tb, out MethodBuilder mb)
+			{
+				tb = DynamicModuleBuilder.DefineType (t.Name + "PackerType", TypeAttributes.Public);
+				mb = tb.DefineMethod ("Pack", MethodAttributes.Static | MethodAttributes.Public, typeof (void), new Type[] {typeof (MsgPackWriter), t});
+			}
+
+			static void CreateUnpackMethodBuilder (Type t, out TypeBuilder tb, out MethodBuilder mb)
+			{
+				tb = DynamicModuleBuilder.DefineType (t.Name + "UnpackerType", TypeAttributes.Public);
+				mb = tb.DefineMethod ("Unpack", MethodAttributes.Static | MethodAttributes.Public, t, new Type[] {typeof (MsgPackReader)});
+			}
+
+			internal static IDictionary<string,int> LookupMemberMapping (Type t)
+			{
+				IDictionary<string, int> mapping;
+				lock (UnpackMemberMappings) {
+					if (!UnpackMemberMappings.TryGetValue (t, out mapping)) {
+						mapping = new Dictionary<string, int> ();
+						UnpackMemberMappings.Add (t, mapping);
+					}
+				}
+				return mapping;
+			}
+		}
+		#endregion
+
+		#region default pack/unpack methods
+		internal static class DefaultPackMethods
+		{
+			public static void Register (Dictionary<Type, MethodInfo> packMethods, Dictionary<Type, MethodInfo> unpackMethods)
+			{
+				RegisterPackMethods (packMethods);
+				RegisterUnpackMethods (unpackMethods);
+			}
+
+			#region Pack
+			static void RegisterPackMethods (Dictionary<Type, MethodInfo> packMethods)
+			{
+				Type type = typeof (DefaultPackMethods);
+				MethodInfo[] methods = type.GetMethods (BindingFlags.Static | BindingFlags.NonPublic);
+				string methodName = "Pack";
+				for (int i = 0; i < methods.Length; i ++) {
+					if (!methodName.Equals (methods[i].Name))
+						continue;
+					ParameterInfo[] parameters = methods[i].GetParameters ();
+					if (parameters.Length != 2 || parameters[0].ParameterType != typeof (MsgPackWriter))
+						continue;
+					packMethods.Add (parameters[1].ParameterType, methods[i]);
+				}
+			}
+
+			internal static void Pack (MsgPackWriter writer, string x)
+			{
+				if (x == null) {
+					writer.WriteNil ();
+				} else {
+					writer.Write (x, false);
+				}
+			}
+			#endregion
+
+			#region Unpack
+			static void RegisterUnpackMethods (Dictionary<Type, MethodInfo> unpackMethods)
+			{
+				BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
+				Type type = typeof (DefaultPackMethods);
+				MethodInfo mi = type.GetMethod ("Unpack_Signed", flags);
+				unpackMethods.Add (typeof (sbyte), mi);
+				unpackMethods.Add (typeof (short), mi);
+				unpackMethods.Add (typeof (int), mi);
+
+				mi = type.GetMethod ("Unpack_Signed64", flags);
+				unpackMethods.Add (typeof (long), mi);
+
+				mi = type.GetMethod ("Unpack_Unsigned", flags);
+				unpackMethods.Add (typeof (byte), mi);
+				unpackMethods.Add (typeof (ushort), mi);
+				unpackMethods.Add (typeof (char), mi);
+				unpackMethods.Add (typeof (uint), mi);
+
+				mi = type.GetMethod ("Unpack_Unsigned64", flags);
+				unpackMethods.Add (typeof (ulong), mi);
+
+				mi = type.GetMethod ("Unpack_Boolean", flags);
+				unpackMethods.Add (typeof (bool), mi);
+
+				mi = type.GetMethod ("Unpack_Float", flags);
+				unpackMethods.Add (typeof (float), mi);
+
+				mi = type.GetMethod ("Unpack_Double", flags);
+				unpackMethods.Add (typeof (double), mi);
+
+				mi = type.GetMethod ("Unpack_String", flags);
+				unpackMethods.Add (typeof (string), mi);
+			}
+
+			internal static int Unpack_Signed (MsgPackReader reader)
+			{
+				if (!reader.Read () || !reader.IsSigned ())
+					UnpackFailed ();
+				return reader.ValueSigned;
+			}
+
+			internal static long Unpack_Signed64 (MsgPackReader reader)
+			{
+				if (!reader.Read ())
+					UnpackFailed ();
+				if (reader.IsSigned ())
+					return reader.ValueSigned;
+				if (reader.IsSigned64 ())
+					return reader.ValueSigned64;
+				UnpackFailed ();
+				return 0; // unused
+			}
+
+			internal static uint Unpack_Unsigned (MsgPackReader reader)
+			{
+				if (!reader.Read () || !reader.IsUnsigned ())
+					UnpackFailed ();
+				return reader.ValueUnsigned;
+			}
+
+			internal static ulong Unpack_Unsigned64 (MsgPackReader reader)
+			{
+				if (!reader.Read ())
+					UnpackFailed ();
+				if (reader.IsUnsigned ())
+					return reader.ValueUnsigned;
+				if (reader.IsUnsigned64 ())
+					return reader.ValueUnsigned64;
+				UnpackFailed ();
+				return 0; // unused
+			}
+
+			internal static bool Unpack_Boolean (MsgPackReader reader)
+			{
+				if (!reader.Read () || !reader.IsBoolean ())
+					UnpackFailed ();
+				return reader.ValueBoolean;
+			}
+
+			internal static float Unpack_Float (MsgPackReader reader)
+			{
+				if (!reader.Read () || reader.Type != TypePrefixes.Float)
+					UnpackFailed ();
+				return reader.ValueFloat;
+			}
+
+			internal static double Unpack_Double (MsgPackReader reader)
+			{
+				if (!reader.Read () || reader.Type != TypePrefixes.Double)
+					UnpackFailed ();
+				return reader.ValueDouble;
+			}
+
+			internal static string Unpack_String (MsgPackReader reader)
+			{
+				if (!reader.Read () || !reader.IsRaw ())
+					UnpackFailed ();
+				return reader.ReadRawString ();
+			}
+
+			internal static void UnpackFailed ()
+			{
+				throw new FormatException ();
+			}
+			#endregion
+		}
+		#endregion
+	}
+}