Mercurial > hg > Database > jungle-sharp
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 + } +}