mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 04:52:59 +01:00
MessagePack for C# was moved to https://github.com/msgpack/msgpack-cli
This commit is contained in:
parent
980a6529c1
commit
13ce808c47
@ -1,21 +0,0 @@
|
|||||||
TARGET=MsgPack.dll
|
|
||||||
TEST_TARGET=MsgPack.Test.dll
|
|
||||||
|
|
||||||
SRC=$(shell find MsgPack -name "*.cs")
|
|
||||||
TEST_SRC=$(shell find MsgPack.Test -name "*.cs")
|
|
||||||
|
|
||||||
MONO_CC=mcs
|
|
||||||
NUNIT_CONSOLE=nunit-console
|
|
||||||
|
|
||||||
all: $(TARGET)
|
|
||||||
test: $(TEST_TARGET) $(TARGET)
|
|
||||||
clean:
|
|
||||||
rm -f $(TARGET) $(TEST_TARGET)
|
|
||||||
run-test:
|
|
||||||
$(NUNIT_CONSOLE) $(TEST_TARGET)
|
|
||||||
|
|
||||||
$(TARGET): $(SRC)
|
|
||||||
$(MONO_CC) -out:$@ -t:library -unsafe+ $(SRC)
|
|
||||||
|
|
||||||
$(TEST_TARGET): $(TEST_SRC) $(TARGET)
|
|
||||||
$(MONO_CC) -out:$@ -t:library -r:$(TARGET) -r:nunit.framework.dll $(TEST_SRC)
|
|
@ -1,26 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle ("MsgPack UnitTest")]
|
|
||||||
[assembly: AssemblyProduct ("MsgPack UnitTest")]
|
|
||||||
[assembly: AssemblyDescription ("MessagePack Serializer for .NET UnitTests")]
|
|
||||||
[assembly: AssemblyCopyright ("Copyright © 2011 Kazuki Oikawa")]
|
|
||||||
|
|
||||||
[assembly: ComVisible (false)]
|
|
||||||
[assembly: AssemblyVersion ("0.1.*")]
|
|
@ -1,89 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Linq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace MsgPack.Test
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class BoxingPackerTests
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void NullTest ()
|
|
||||||
{
|
|
||||||
BoxingPacker packer = new BoxingPacker ();
|
|
||||||
Assert.IsNull (packer.Unpack (packer.Pack (null)));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void PrimitiveTypeTest ()
|
|
||||||
{
|
|
||||||
BoxingPacker packer = new BoxingPacker ();
|
|
||||||
RoundtripTest<int> (packer, 12345);
|
|
||||||
RoundtripTest<ulong> (packer, 1234567890123456789UL);
|
|
||||||
RoundtripTest<double> (packer, Math.PI);
|
|
||||||
RoundtripTest<bool> (packer, true);
|
|
||||||
RoundtripTest<bool> (packer, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ArrayTest ()
|
|
||||||
{
|
|
||||||
BoxingPacker packer = new BoxingPacker ();
|
|
||||||
RoundtripTest<object[]> (packer, new object[0]);
|
|
||||||
RoundtripTest<object[]> (packer, new object[]{
|
|
||||||
int.MinValue, int.MaxValue, 1234567890123456789UL, ulong.MaxValue,
|
|
||||||
float.MinValue, float.MaxValue, float.Epsilon, float.NaN, float.PositiveInfinity, float.NegativeInfinity,
|
|
||||||
double.MinValue, double.MaxValue, double.Epsilon, double.NaN, double.PositiveInfinity, double.NegativeInfinity,
|
|
||||||
null, true, false, new object[] {
|
|
||||||
new object[] {1, 2, 3},
|
|
||||||
new object[] {Math.PI, true}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void MapTest ()
|
|
||||||
{
|
|
||||||
BoxingPacker packer = new BoxingPacker ();
|
|
||||||
Dictionary<object, object> dic = new Dictionary<object,object> ();
|
|
||||||
Dictionary<object, object> dic2 = new Dictionary<object,object> ();
|
|
||||||
RoundtripTest<IDictionary<object,object>> (packer, dic);
|
|
||||||
|
|
||||||
dic2.Add (123, 456);
|
|
||||||
dic2.Add (234, 567);
|
|
||||||
dic2.Add (345, 678);
|
|
||||||
|
|
||||||
dic.Add (0, 0.123);
|
|
||||||
dic.Add (Math.PI, true);
|
|
||||||
dic.Add (false, new object[] {1, 2, 3});
|
|
||||||
dic.Add (1, new Dictionary<object,object> (dic2));
|
|
||||||
RoundtripTest<IDictionary<object,object>> (packer, dic);
|
|
||||||
|
|
||||||
dic[1] = ((Dictionary<object,object>)dic[1]).ToArray ();
|
|
||||||
Assert.AreEqual (dic, packer.Unpack (packer.Pack (dic.ToArray ())));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoundtripTest<T> (BoxingPacker packer, T obj)
|
|
||||||
{
|
|
||||||
T obj2 = (T)packer.Unpack (packer.Pack (obj));
|
|
||||||
Assert.AreEqual (obj, obj2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// 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 NUnit.Framework;
|
|
||||||
using TestA_Class = MsgPack.Test.ObjectPackerTests.TestA_Class;
|
|
||||||
using TestB_Class = MsgPack.Test.ObjectPackerTests.TestB_Class;
|
|
||||||
|
|
||||||
namespace MsgPack.Test
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class CompiledPackerTests
|
|
||||||
{
|
|
||||||
CompiledPacker _mbImpl = new CompiledPacker (false);
|
|
||||||
CompiledPacker _dynImpl = new CompiledPacker (true);
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestA_MethodBuilder ()
|
|
||||||
{
|
|
||||||
TestA (_mbImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestA_DynamicMethod ()
|
|
||||||
{
|
|
||||||
TestA (_dynImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestB_MethodBuilder ()
|
|
||||||
{
|
|
||||||
TestB (_mbImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestB_DynamicMethod ()
|
|
||||||
{
|
|
||||||
TestB (_dynImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestA (CompiledPacker packer)
|
|
||||||
{
|
|
||||||
TestA_Class obj0 = new TestA_Class ();
|
|
||||||
TestA_Class obj1 = packer.Unpack<TestA_Class> (packer.Pack<TestA_Class> (obj0));
|
|
||||||
obj0.Check (obj1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestB (CompiledPacker packer)
|
|
||||||
{
|
|
||||||
TestB_Class obj0 = TestB_Class.Create ();
|
|
||||||
TestB_Class obj1 = packer.Unpack<TestB_Class> (packer.Pack<TestB_Class> (obj0));
|
|
||||||
obj0.Check (obj1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectGuid>{CE24167B-8F0A-4670-BD1E-3C283311E86B}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>MsgPack.Test</RootNamespace>
|
|
||||||
<AssemblyName>MsgPack.Test</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<StartupObject />
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="nunit.framework, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
|
||||||
<Compile Include="BoxingPackerTests.cs" />
|
|
||||||
<Compile Include="CompiledPackerTests.cs" />
|
|
||||||
<Compile Include="ObjectPackerTests.cs" />
|
|
||||||
<Compile Include="ReaderWriterTests.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\MsgPack\MsgPack.csproj">
|
|
||||||
<Project>{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}</Project>
|
|
||||||
<Name>MsgPack</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
@ -1,131 +0,0 @@
|
|||||||
//
|
|
||||||
// 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 NUnit.Framework;
|
|
||||||
|
|
||||||
namespace MsgPack.Test
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class ObjectPackerTests
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void TestA ()
|
|
||||||
{
|
|
||||||
ObjectPacker packer = new ObjectPacker ();
|
|
||||||
TestA_Class obj0 = new TestA_Class ();
|
|
||||||
TestA_Class obj1 = packer.Unpack<TestA_Class> (packer.Pack (obj0));
|
|
||||||
obj0.Check (obj1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestB ()
|
|
||||||
{
|
|
||||||
ObjectPacker packer = new ObjectPacker ();
|
|
||||||
TestB_Class obj0 = TestB_Class.Create ();
|
|
||||||
TestB_Class obj1 = packer.Unpack<TestB_Class> (packer.Pack (obj0));
|
|
||||||
obj0.Check (obj1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TestA_Class
|
|
||||||
{
|
|
||||||
public bool a;
|
|
||||||
public byte b;
|
|
||||||
public sbyte c;
|
|
||||||
public short d;
|
|
||||||
public ushort e;
|
|
||||||
public int f;
|
|
||||||
public uint g;
|
|
||||||
public long h;
|
|
||||||
public ulong i;
|
|
||||||
public float j;
|
|
||||||
public double k;
|
|
||||||
public int[] l;
|
|
||||||
public string m;
|
|
||||||
|
|
||||||
public TestA_Class ()
|
|
||||||
{
|
|
||||||
Random rnd = new Random ();
|
|
||||||
a = rnd.NextDouble () < 0.5;
|
|
||||||
b = (byte)rnd.Next ();
|
|
||||||
c = (sbyte)rnd.Next ();
|
|
||||||
d = (short)rnd.Next ();
|
|
||||||
e = (ushort)rnd.Next ();
|
|
||||||
f = (int)rnd.Next ();
|
|
||||||
g = (uint)rnd.Next ();
|
|
||||||
h = (long)rnd.Next ();
|
|
||||||
i = (ulong)rnd.Next ();
|
|
||||||
j = (float)rnd.NextDouble ();
|
|
||||||
k = (double)rnd.NextDouble ();
|
|
||||||
l = new int[rnd.Next () & 0xff];
|
|
||||||
for (int z = 0; z < l.Length; z ++)
|
|
||||||
l[z] = rnd.Next ();
|
|
||||||
|
|
||||||
byte[] buf = new byte[rnd.Next() & 0xff];
|
|
||||||
rnd.NextBytes (buf);
|
|
||||||
m = Convert.ToBase64String (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Check (TestA_Class other)
|
|
||||||
{
|
|
||||||
Assert.AreEqual (this.a, other.a);
|
|
||||||
Assert.AreEqual (this.b, other.b);
|
|
||||||
Assert.AreEqual (this.c, other.c);
|
|
||||||
Assert.AreEqual (this.d, other.d);
|
|
||||||
Assert.AreEqual (this.e, other.e);
|
|
||||||
Assert.AreEqual (this.f, other.f);
|
|
||||||
Assert.AreEqual (this.g, other.g);
|
|
||||||
Assert.AreEqual (this.h, other.h);
|
|
||||||
Assert.AreEqual (this.i, other.i);
|
|
||||||
Assert.AreEqual (this.j, other.j);
|
|
||||||
Assert.AreEqual (this.k, other.k);
|
|
||||||
Assert.AreEqual (this.l, other.l);
|
|
||||||
Assert.AreEqual (this.m, other.m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TestB_Class
|
|
||||||
{
|
|
||||||
public TestA_Class x;
|
|
||||||
public TestB_Class nested;
|
|
||||||
public int[] list;
|
|
||||||
|
|
||||||
public static TestB_Class Create ()
|
|
||||||
{
|
|
||||||
return Create (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static TestB_Class Create (int level)
|
|
||||||
{
|
|
||||||
TestB_Class obj = new TestB_Class ();
|
|
||||||
obj.x = new TestA_Class ();
|
|
||||||
if (level < 10)
|
|
||||||
obj.nested = Create (level + 1);
|
|
||||||
if ((level % 2) == 0)
|
|
||||||
obj.list = new int[] {level, 0, level, int.MaxValue, level};
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Check (TestB_Class other)
|
|
||||||
{
|
|
||||||
x.Check (other.x);
|
|
||||||
if (nested != null)
|
|
||||||
nested.Check (other.nested);
|
|
||||||
Assert.AreEqual (list, other.list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,331 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.IO;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace MsgPack.Test
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class ReaderWriterTests
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void SignedNumberTest ()
|
|
||||||
{
|
|
||||||
long[] nums = new long[]{
|
|
||||||
/* positive fixnum */
|
|
||||||
0, 1, 126, 127,
|
|
||||||
|
|
||||||
/* negative fixnum */
|
|
||||||
-1, -2, -31, -32,
|
|
||||||
|
|
||||||
/* int8 */
|
|
||||||
-128, -33,
|
|
||||||
|
|
||||||
/* int16 */
|
|
||||||
-32768, -129, 128, 32767,
|
|
||||||
|
|
||||||
/* int32 */
|
|
||||||
-2147483648, -32769, 32768, 2147483647,
|
|
||||||
|
|
||||||
/* int64 */
|
|
||||||
-9223372036854775808, -2147483649, 2147483648, 9223372036854775807
|
|
||||||
};
|
|
||||||
byte[] expectedBytes = new byte[] {
|
|
||||||
/* positive fixnum */
|
|
||||||
0, 1, 126, 127,
|
|
||||||
|
|
||||||
/* negative fixnum */
|
|
||||||
0xff, 0xfe, 0xe1, 0xe0,
|
|
||||||
|
|
||||||
/* int8 */
|
|
||||||
0xd0, 0x80,
|
|
||||||
0xd0, 0xdf,
|
|
||||||
|
|
||||||
/* int16 */
|
|
||||||
0xd1, 0x80, 0x00,
|
|
||||||
0xd1, 0xff, 0x7f,
|
|
||||||
0xd1, 0x00, 0x80,
|
|
||||||
0xd1, 0x7f, 0xff,
|
|
||||||
|
|
||||||
/* int32 */
|
|
||||||
0xd2, 0x80, 0x00, 0x00, 0x00,
|
|
||||||
0xd2, 0xff, 0xff, 0x7f, 0xff,
|
|
||||||
0xd2, 0x00, 0x00, 0x80, 0x00,
|
|
||||||
0xd2, 0x7f, 0xff, 0xff, 0xff,
|
|
||||||
|
|
||||||
/* int64 */
|
|
||||||
0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff,
|
|
||||||
0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
|
|
||||||
0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
for (int i = 0; i < nums.Length; i ++) {
|
|
||||||
writer.Write (nums[i]);
|
|
||||||
}
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
for (int i = 0; i < nums.Length; i ++) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.IsSigned () || reader.IsSigned64 ());
|
|
||||||
if (reader.IsSigned64 ()) {
|
|
||||||
Assert.AreEqual (nums[i], reader.ValueSigned64);
|
|
||||||
} else {
|
|
||||||
Assert.AreEqual (nums[i], reader.ValueSigned);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void UnsignedNumberTest ()
|
|
||||||
{
|
|
||||||
ulong[] nums = new ulong[]{
|
|
||||||
/* uint8 */
|
|
||||||
128, byte.MaxValue,
|
|
||||||
|
|
||||||
/* uint16 */
|
|
||||||
byte.MaxValue + 1, ushort.MaxValue,
|
|
||||||
|
|
||||||
/* uint32 */
|
|
||||||
ushort.MaxValue + 1U, uint.MaxValue,
|
|
||||||
|
|
||||||
/* uint64 */
|
|
||||||
uint.MaxValue + 1UL, ulong.MaxValue
|
|
||||||
};
|
|
||||||
byte[] expectedBytes = new byte[] {
|
|
||||||
/* int8 */
|
|
||||||
0xcc, 0x80,
|
|
||||||
0xcc, 0xff,
|
|
||||||
|
|
||||||
/* int16 */
|
|
||||||
0xcd, 0x01, 0x00,
|
|
||||||
0xcd, 0xff, 0xff,
|
|
||||||
|
|
||||||
/* int32 */
|
|
||||||
0xce, 0x00, 0x01, 0x00, 0x00,
|
|
||||||
0xce, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
|
|
||||||
/* int64 */
|
|
||||||
0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
for (int i = 0; i < nums.Length; i ++) {
|
|
||||||
writer.Write (nums[i]);
|
|
||||||
}
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
for (int i = 0; i < nums.Length; i ++) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.IsUnsigned () || reader.IsUnsigned64 ());
|
|
||||||
if (reader.IsUnsigned64 ()) {
|
|
||||||
Assert.AreEqual (nums[i], reader.ValueUnsigned64);
|
|
||||||
} else {
|
|
||||||
Assert.AreEqual (nums[i], reader.ValueUnsigned);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void NilTest ()
|
|
||||||
{
|
|
||||||
byte[] expectedBytes = new byte[] {
|
|
||||||
0xc0
|
|
||||||
};
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
writer.WriteNil ();
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.Type == TypePrefixes.Nil);
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void BooleanTest ()
|
|
||||||
{
|
|
||||||
byte[] expectedBytes = new byte[] {
|
|
||||||
0xc3, 0xc2
|
|
||||||
};
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
writer.Write (true);
|
|
||||||
writer.Write (false);
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.Type == TypePrefixes.True);
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.Type == TypePrefixes.False);
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void FloatingPointTest ()
|
|
||||||
{
|
|
||||||
byte[] expectedBytes = new byte[] {
|
|
||||||
0xca, 0x40, 0x49, 0x0f, 0xdb,
|
|
||||||
0xcb, 0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18,
|
|
||||||
};
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
writer.Write ((float)Math.PI);
|
|
||||||
writer.Write (Math.PI);
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.Type == TypePrefixes.Float);
|
|
||||||
Assert.AreEqual ((float)Math.PI, reader.ValueFloat);
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.Type == TypePrefixes.Double);
|
|
||||||
Assert.AreEqual (Math.PI, reader.ValueDouble);
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void RawTest ()
|
|
||||||
{
|
|
||||||
Random rnd = new Random ();
|
|
||||||
|
|
||||||
byte[][] rawList = new byte[][] {
|
|
||||||
new byte[0],
|
|
||||||
new byte[1],
|
|
||||||
new byte[31],
|
|
||||||
new byte[32],
|
|
||||||
new byte[65535],
|
|
||||||
new byte[65536]
|
|
||||||
};
|
|
||||||
byte[][] headerSizeList = new byte[][] {
|
|
||||||
new byte[] {0xa0},
|
|
||||||
new byte[] {0xa1},
|
|
||||||
new byte[] {0xbf},
|
|
||||||
new byte[] {0xda, 0x00, 0x20},
|
|
||||||
new byte[] {0xda, 0xff, 0xff},
|
|
||||||
new byte[] {0xdb, 0x00, 0x01, 0x00, 0x00},
|
|
||||||
};
|
|
||||||
byte[] expectedBytes = new byte[131135 + 1 * 3 + 3 * 2 + 5];
|
|
||||||
for (int i = 0, offset = 0; i < rawList.Length; i ++) {
|
|
||||||
rnd.NextBytes (rawList[i]);
|
|
||||||
|
|
||||||
Buffer.BlockCopy (headerSizeList[i], 0, expectedBytes, offset, headerSizeList[i].Length);
|
|
||||||
offset += headerSizeList[i].Length;
|
|
||||||
Buffer.BlockCopy (rawList[i], 0, expectedBytes, offset, rawList[i].Length);
|
|
||||||
offset += rawList[i].Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
for (int i = 0; i < rawList.Length; i ++)
|
|
||||||
writer.Write (rawList[i]);
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
for (int i = 0; i < rawList.Length; i ++) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.AreEqual (rawList[i].Length, (int)reader.Length);
|
|
||||||
byte[] tmp = new byte[(int)reader.Length];
|
|
||||||
reader.ReadValueRaw (tmp, 0, tmp.Length);
|
|
||||||
Assert.AreEqual (rawList[i], tmp);
|
|
||||||
}
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ArrayMapRawHeaderTest ()
|
|
||||||
{
|
|
||||||
int[] list = new int[] {
|
|
||||||
0, 1, 15, 16, 31, 32, 65535, 65536
|
|
||||||
};
|
|
||||||
byte[] expectedBytes = new byte[] {
|
|
||||||
/* size=0 */
|
|
||||||
0x90, /* array */
|
|
||||||
0x80, /* map */
|
|
||||||
0xa0, /* raw */
|
|
||||||
|
|
||||||
/* size=1 */
|
|
||||||
0x91,
|
|
||||||
0x81,
|
|
||||||
0xa1,
|
|
||||||
|
|
||||||
/* size=15 */
|
|
||||||
0x9f,
|
|
||||||
0x8f,
|
|
||||||
0xaf,
|
|
||||||
|
|
||||||
/* size=16 */
|
|
||||||
0xdc, 0x00, 0x10, /* array16 */
|
|
||||||
0xde, 0x00, 0x10, /* map16 */
|
|
||||||
0xb0, /* fix raw */
|
|
||||||
|
|
||||||
/* size=31 */
|
|
||||||
0xdc, 0x00, 0x1f, /* array16 */
|
|
||||||
0xde, 0x00, 0x1f, /* map16 */
|
|
||||||
0xbf, /* fix raw */
|
|
||||||
|
|
||||||
/* size=32 */
|
|
||||||
0xdc, 0x00, 0x20, /* array16 */
|
|
||||||
0xde, 0x00, 0x20, /* map16 */
|
|
||||||
0xda, 0x00, 0x20, /* raw16 */
|
|
||||||
|
|
||||||
/* size=65535 */
|
|
||||||
0xdc, 0xff, 0xff, /* array16 */
|
|
||||||
0xde, 0xff, 0xff, /* map16 */
|
|
||||||
0xda, 0xff, 0xff, /* raw16 */
|
|
||||||
|
|
||||||
/* size=65536 */
|
|
||||||
0xdd, 0x00, 0x01, 0x00, 0x00, /* array32 */
|
|
||||||
0xdf, 0x00, 0x01, 0x00, 0x00, /* map32 */
|
|
||||||
0xdb, 0x00, 0x01, 0x00, 0x00, /* raw32 */
|
|
||||||
};
|
|
||||||
|
|
||||||
Test (delegate (MsgPackWriter writer) {
|
|
||||||
for (int i = 0; i < list.Length; i ++) {
|
|
||||||
writer.WriteArrayHeader (list[i]);
|
|
||||||
writer.WriteMapHeader (list[i]);
|
|
||||||
writer.WriteRawHeader (list[i]);
|
|
||||||
}
|
|
||||||
}, delegate (MsgPackReader reader) {
|
|
||||||
for (int i = 0; i < list.Length; i ++) {
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.IsArray ());
|
|
||||||
Assert.AreEqual (list[i], (int)reader.Length);
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.IsMap ());
|
|
||||||
Assert.AreEqual (list[i], (int)reader.Length);
|
|
||||||
Assert.IsTrue (reader.Read ());
|
|
||||||
Assert.IsTrue (reader.IsRaw ());
|
|
||||||
Assert.AreEqual (list[i], (int)reader.Length);
|
|
||||||
}
|
|
||||||
}, expectedBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate void WriteDelegate (MsgPackWriter writer);
|
|
||||||
delegate void ReadDelegate (MsgPackReader reader);
|
|
||||||
void Test (WriteDelegate writeProc, ReadDelegate readProc, byte[] expectedBytes)
|
|
||||||
{
|
|
||||||
byte[] raw;
|
|
||||||
using (MemoryStream ms = new MemoryStream ()) {
|
|
||||||
MsgPackWriter writer = new MsgPackWriter (ms);
|
|
||||||
writeProc (writer);
|
|
||||||
raw = ms.ToArray ();
|
|
||||||
}
|
|
||||||
Assert.AreEqual (expectedBytes, raw, "pack failed");
|
|
||||||
using (MemoryStream ms = new MemoryStream (raw)) {
|
|
||||||
MsgPackReader reader = new MsgPackReader (ms);
|
|
||||||
readProc (reader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
|
||||||
# Visual Studio 2010
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack", "MsgPack\MsgPack.csproj", "{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Test", "MsgPack.Test/MsgPack.Test.csproj", "{CE24167B-8F0A-4670-BD1E-3C283311E86B}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{CE24167B-8F0A-4670-BD1E-3C283311E86B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{CE24167B-8F0A-4670-BD1E-3C283311E86B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{CE24167B-8F0A-4670-BD1E-3C283311E86B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle ("MsgPack")]
|
|
||||||
[assembly: AssemblyProduct ("MsgPack")]
|
|
||||||
[assembly: AssemblyDescription ("MessagePack Serializer for .NET")]
|
|
||||||
[assembly: AssemblyCopyright ("Copyright © 2011 Kazuki Oikawa")]
|
|
||||||
|
|
||||||
[assembly: ComVisible (false)]
|
|
||||||
[assembly: AssemblyVersion ("0.1.*")]
|
|
||||||
[assembly: InternalsVisibleTo (MsgPack.CompiledPacker.MethodBuilderPacker.AssemblyName)]
|
|
@ -1,184 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public class BoxingPacker
|
|
||||||
{
|
|
||||||
static Type KeyValuePairDefinitionType;
|
|
||||||
|
|
||||||
static BoxingPacker ()
|
|
||||||
{
|
|
||||||
KeyValuePairDefinitionType = typeof (KeyValuePair<object,object>).GetGenericTypeDefinition ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Pack (Stream strm, object o)
|
|
||||||
{
|
|
||||||
MsgPackWriter writer = new MsgPackWriter (strm);
|
|
||||||
Pack (writer, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Pack (object o)
|
|
||||||
{
|
|
||||||
using (MemoryStream ms = new MemoryStream ()) {
|
|
||||||
Pack (ms, o);
|
|
||||||
return ms.ToArray ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Pack (MsgPackWriter writer, object o)
|
|
||||||
{
|
|
||||||
if (o == null) {
|
|
||||||
writer.WriteNil ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type t = o.GetType ();
|
|
||||||
if (t.IsPrimitive) {
|
|
||||||
if (t.Equals (typeof (int))) writer.Write ((int)o);
|
|
||||||
else if (t.Equals (typeof (uint))) writer.Write ((uint)o);
|
|
||||||
else if (t.Equals (typeof (float))) writer.Write ((float)o);
|
|
||||||
else if (t.Equals (typeof (double))) writer.Write ((double)o);
|
|
||||||
else if (t.Equals (typeof (long))) writer.Write ((long)o);
|
|
||||||
else if (t.Equals (typeof (ulong))) writer.Write ((ulong)o);
|
|
||||||
else if (t.Equals (typeof (bool))) writer.Write ((bool)o);
|
|
||||||
else if (t.Equals (typeof (byte))) writer.Write ((byte)o);
|
|
||||||
else if (t.Equals (typeof (sbyte))) writer.Write ((sbyte)o);
|
|
||||||
else if (t.Equals (typeof (short))) writer.Write ((short)o);
|
|
||||||
else if (t.Equals (typeof (ushort))) writer.Write ((ushort)o);
|
|
||||||
else throw new NotSupportedException (); // char?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDictionary dic = o as IDictionary;
|
|
||||||
if (dic != null) {
|
|
||||||
writer.WriteMapHeader (dic.Count);
|
|
||||||
foreach (System.Collections.DictionaryEntry e in dic) {
|
|
||||||
Pack (writer, e.Key);
|
|
||||||
Pack (writer, e.Value);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.IsArray) {
|
|
||||||
Array ary = (Array)o;
|
|
||||||
Type et = t.GetElementType ();
|
|
||||||
|
|
||||||
// KeyValuePair<K,V>[] (Map Type)
|
|
||||||
if (et.IsGenericType && et.GetGenericTypeDefinition ().Equals (KeyValuePairDefinitionType)) {
|
|
||||||
PropertyInfo propKey = et.GetProperty ("Key");
|
|
||||||
PropertyInfo propValue = et.GetProperty ("Value");
|
|
||||||
writer.WriteMapHeader (ary.Length);
|
|
||||||
for (int i = 0; i < ary.Length; i ++) {
|
|
||||||
object e = ary.GetValue (i);
|
|
||||||
Pack (writer, propKey.GetValue (e, null));
|
|
||||||
Pack (writer, propValue.GetValue (e, null));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Array
|
|
||||||
writer.WriteArrayHeader (ary.Length);
|
|
||||||
for (int i = 0; i < ary.Length; i ++)
|
|
||||||
Pack (writer, ary.GetValue (i));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Unpack (Stream strm)
|
|
||||||
{
|
|
||||||
MsgPackReader reader = new MsgPackReader (strm);
|
|
||||||
return Unpack (reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Unpack (byte[] buf, int offset, int size)
|
|
||||||
{
|
|
||||||
using (MemoryStream ms = new MemoryStream (buf, offset, size)) {
|
|
||||||
return Unpack (ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Unpack (byte[] buf)
|
|
||||||
{
|
|
||||||
return Unpack (buf, 0, buf.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
object Unpack (MsgPackReader reader)
|
|
||||||
{
|
|
||||||
if (!reader.Read ())
|
|
||||||
throw new FormatException ();
|
|
||||||
|
|
||||||
switch (reader.Type) {
|
|
||||||
case TypePrefixes.PositiveFixNum:
|
|
||||||
case TypePrefixes.NegativeFixNum:
|
|
||||||
case TypePrefixes.Int8:
|
|
||||||
case TypePrefixes.Int16:
|
|
||||||
case TypePrefixes.Int32:
|
|
||||||
return reader.ValueSigned;
|
|
||||||
case TypePrefixes.Int64:
|
|
||||||
return reader.ValueSigned64;
|
|
||||||
case TypePrefixes.UInt8:
|
|
||||||
case TypePrefixes.UInt16:
|
|
||||||
case TypePrefixes.UInt32:
|
|
||||||
return reader.ValueUnsigned;
|
|
||||||
case TypePrefixes.UInt64:
|
|
||||||
return reader.ValueUnsigned64;
|
|
||||||
case TypePrefixes.True:
|
|
||||||
return true;
|
|
||||||
case TypePrefixes.False:
|
|
||||||
return false;
|
|
||||||
case TypePrefixes.Float:
|
|
||||||
return reader.ValueFloat;
|
|
||||||
case TypePrefixes.Double:
|
|
||||||
return reader.ValueDouble;
|
|
||||||
case TypePrefixes.Nil:
|
|
||||||
return null;
|
|
||||||
case TypePrefixes.FixRaw:
|
|
||||||
case TypePrefixes.Raw16:
|
|
||||||
case TypePrefixes.Raw32:
|
|
||||||
byte[] raw = new byte[reader.Length];
|
|
||||||
reader.ReadValueRaw (raw, 0, raw.Length);
|
|
||||||
return raw;
|
|
||||||
case TypePrefixes.FixArray:
|
|
||||||
case TypePrefixes.Array16:
|
|
||||||
case TypePrefixes.Array32:
|
|
||||||
object[] ary = new object[reader.Length];
|
|
||||||
for (int i = 0; i < ary.Length; i ++)
|
|
||||||
ary[i] = Unpack (reader);
|
|
||||||
return ary;
|
|
||||||
case TypePrefixes.FixMap:
|
|
||||||
case TypePrefixes.Map16:
|
|
||||||
case TypePrefixes.Map32:
|
|
||||||
IDictionary<object, object> dic = new Dictionary<object, object> ((int)reader.Length);
|
|
||||||
int count = (int)reader.Length;
|
|
||||||
for (int i = 0; i < count; i ++) {
|
|
||||||
object k = Unpack (reader);
|
|
||||||
object v = Unpack (reader);
|
|
||||||
dic.Add (k, v);
|
|
||||||
}
|
|
||||||
return dic;
|
|
||||||
default:
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,549 +0,0 @@
|
|||||||
//
|
|
||||||
// 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
|
|
||||||
{
|
|
||||||
protected 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;
|
|
||||||
List<MemberInfo> list = new 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;
|
|
||||||
|
|
||||||
protected 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;
|
|
||||||
List<MemberInfo> list = new 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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,191 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Reflection;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace MsgPack.Compiler
|
|
||||||
{
|
|
||||||
public static class EmitExtensions
|
|
||||||
{
|
|
||||||
public static void EmitLd (this ILGenerator il, Variable v)
|
|
||||||
{
|
|
||||||
switch (v.VarType) {
|
|
||||||
case VariableType.Arg:
|
|
||||||
EmitLdarg (il, v);
|
|
||||||
break;
|
|
||||||
case VariableType.Local:
|
|
||||||
EmitLdloc (il, v);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLd (this ILGenerator il, params Variable[] list)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < list.Length; i ++)
|
|
||||||
EmitLd (il, list[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLdarg (this ILGenerator il, Variable v)
|
|
||||||
{
|
|
||||||
if (v.VarType != VariableType.Arg)
|
|
||||||
throw new ArgumentException ();
|
|
||||||
|
|
||||||
switch (v.Index) {
|
|
||||||
case 0: il.Emit (OpCodes.Ldarg_0); return;
|
|
||||||
case 1: il.Emit (OpCodes.Ldarg_1); return;
|
|
||||||
case 2: il.Emit (OpCodes.Ldarg_2); return;
|
|
||||||
case 3: il.Emit (OpCodes.Ldarg_3); return;
|
|
||||||
}
|
|
||||||
if (v.Index <= byte.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Ldarg_S, (byte)v.Index);
|
|
||||||
} else if (v.Index <= short.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Ldarg, v.Index);
|
|
||||||
} else {
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLdloc (this ILGenerator il, Variable v)
|
|
||||||
{
|
|
||||||
if (v.VarType != VariableType.Local)
|
|
||||||
throw new ArgumentException ();
|
|
||||||
|
|
||||||
switch (v.Index) {
|
|
||||||
case 0: il.Emit (OpCodes.Ldloc_0); return;
|
|
||||||
case 1: il.Emit (OpCodes.Ldloc_1); return;
|
|
||||||
case 2: il.Emit (OpCodes.Ldloc_2); return;
|
|
||||||
case 3: il.Emit (OpCodes.Ldloc_3); return;
|
|
||||||
}
|
|
||||||
if (v.Index <= byte.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Ldloc_S, (byte)v.Index);
|
|
||||||
} else if (v.Index <= short.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Ldloc, v.Index);
|
|
||||||
} else {
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitSt (this ILGenerator il, Variable v)
|
|
||||||
{
|
|
||||||
switch (v.VarType) {
|
|
||||||
case VariableType.Arg:
|
|
||||||
EmitStarg (il, v);
|
|
||||||
break;
|
|
||||||
case VariableType.Local:
|
|
||||||
EmitStloc (il, v);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitStarg (this ILGenerator il, Variable v)
|
|
||||||
{
|
|
||||||
if (v.VarType != VariableType.Arg)
|
|
||||||
throw new ArgumentException ();
|
|
||||||
|
|
||||||
if (v.Index <= byte.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Starg_S, (byte)v.Index);
|
|
||||||
} else if (v.Index <= short.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Starg, v.Index);
|
|
||||||
} else {
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitStloc (this ILGenerator il, Variable v)
|
|
||||||
{
|
|
||||||
if (v.VarType != VariableType.Local)
|
|
||||||
throw new ArgumentException ();
|
|
||||||
|
|
||||||
switch (v.Index) {
|
|
||||||
case 0: il.Emit (OpCodes.Stloc_0); return;
|
|
||||||
case 1: il.Emit (OpCodes.Stloc_1); return;
|
|
||||||
case 2: il.Emit (OpCodes.Stloc_2); return;
|
|
||||||
case 3: il.Emit (OpCodes.Stloc_3); return;
|
|
||||||
}
|
|
||||||
if (v.Index <= byte.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Stloc_S, (byte)v.Index);
|
|
||||||
} else if (v.Index <= short.MaxValue) {
|
|
||||||
il.Emit (OpCodes.Stloc, v.Index);
|
|
||||||
} else {
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLdc (this ILGenerator il, int v)
|
|
||||||
{
|
|
||||||
switch (v) {
|
|
||||||
case 0: il.Emit (OpCodes.Ldc_I4_0); return;
|
|
||||||
case 1: il.Emit (OpCodes.Ldc_I4_1); return;
|
|
||||||
case 2: il.Emit (OpCodes.Ldc_I4_2); return;
|
|
||||||
case 3: il.Emit (OpCodes.Ldc_I4_3); return;
|
|
||||||
case 4: il.Emit (OpCodes.Ldc_I4_4); return;
|
|
||||||
case 5: il.Emit (OpCodes.Ldc_I4_5); return;
|
|
||||||
case 6: il.Emit (OpCodes.Ldc_I4_6); return;
|
|
||||||
case 7: il.Emit (OpCodes.Ldc_I4_7); return;
|
|
||||||
case 8: il.Emit (OpCodes.Ldc_I4_8); return;
|
|
||||||
case -1: il.Emit (OpCodes.Ldc_I4_M1); return;
|
|
||||||
}
|
|
||||||
if (v <= sbyte.MaxValue && v >= sbyte.MinValue) {
|
|
||||||
il.Emit (OpCodes.Ldc_I4_S, (sbyte)v);
|
|
||||||
} else {
|
|
||||||
il.Emit (OpCodes.Ldc_I4, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLd_False (this ILGenerator il)
|
|
||||||
{
|
|
||||||
il.Emit (OpCodes.Ldc_I4_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLd_True (this ILGenerator il)
|
|
||||||
{
|
|
||||||
il.Emit (OpCodes.Ldc_I4_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLdstr (this ILGenerator il, string v)
|
|
||||||
{
|
|
||||||
il.Emit (OpCodes.Ldstr, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitLdMember (this ILGenerator il, MemberInfo m)
|
|
||||||
{
|
|
||||||
if (m.MemberType == MemberTypes.Field) {
|
|
||||||
il.Emit (OpCodes.Ldfld, (FieldInfo)m);
|
|
||||||
} else if (m.MemberType == MemberTypes.Property) {
|
|
||||||
il.Emit (OpCodes.Callvirt, ((PropertyInfo)m).GetGetMethod (true));
|
|
||||||
} else {
|
|
||||||
throw new ArgumentException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitStMember (this ILGenerator il, MemberInfo m)
|
|
||||||
{
|
|
||||||
if (m.MemberType == MemberTypes.Field) {
|
|
||||||
il.Emit (OpCodes.Stfld, (FieldInfo)m);
|
|
||||||
} else if (m.MemberType == MemberTypes.Property) {
|
|
||||||
il.Emit (OpCodes.Callvirt, ((PropertyInfo)m).GetSetMethod (true));
|
|
||||||
} else {
|
|
||||||
throw new ArgumentException ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,386 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Reflection;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace MsgPack.Compiler
|
|
||||||
{
|
|
||||||
static class PackILGenerator
|
|
||||||
{
|
|
||||||
#region Pack IL Generator
|
|
||||||
public static void EmitPackCode (Type type, MethodInfo mi, ILGenerator il,
|
|
||||||
Func<Type,MemberInfo[]> targetMemberSelector,
|
|
||||||
Func<MemberInfo,string> memberNameFormatter,
|
|
||||||
Func<Type, MethodInfo> lookupPackMethod)
|
|
||||||
{
|
|
||||||
if (type.IsPrimitive || type.IsInterface)
|
|
||||||
throw new NotSupportedException ();
|
|
||||||
|
|
||||||
Variable arg_writer = Variable.CreateArg (0);
|
|
||||||
Variable arg_obj = Variable.CreateArg (1);
|
|
||||||
Variable local_i = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
|
|
||||||
|
|
||||||
if (!type.IsValueType) { // null check
|
|
||||||
Label notNullLabel = il.DefineLabel ();
|
|
||||||
il.EmitLd (arg_obj);
|
|
||||||
il.Emit (OpCodes.Brtrue_S, notNullLabel);
|
|
||||||
il.EmitLd (arg_writer);
|
|
||||||
il.Emit (OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteNil", new Type[0]));
|
|
||||||
il.Emit (OpCodes.Ret);
|
|
||||||
il.MarkLabel (notNullLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.IsArray) {
|
|
||||||
EmitPackArrayCode (mi, il, type, arg_writer, arg_obj, local_i, lookupPackMethod);
|
|
||||||
goto FinallyProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsgPackWriter.WriteMapHeader
|
|
||||||
MemberInfo[] members = targetMemberSelector (type);
|
|
||||||
il.EmitLd (arg_writer);
|
|
||||||
il.EmitLdc (members.Length);
|
|
||||||
il.Emit (OpCodes.Callvirt, typeof (MsgPackWriter).GetMethod("WriteMapHeader", new Type[]{typeof (int)}));
|
|
||||||
|
|
||||||
for (int i = 0; i < members.Length; i ++) {
|
|
||||||
MemberInfo m = members[i];
|
|
||||||
Type mt = m.GetMemberType ();
|
|
||||||
|
|
||||||
// write field-name
|
|
||||||
il.EmitLd (arg_writer);
|
|
||||||
il.EmitLdstr (memberNameFormatter (m));
|
|
||||||
il.EmitLd_True ();
|
|
||||||
il.Emit (OpCodes.Call, typeof (MsgPackWriter).GetMethod("Write", new Type[]{typeof (string), typeof (bool)}));
|
|
||||||
|
|
||||||
// write value
|
|
||||||
EmitPackMemberValueCode (mt, il, arg_writer, arg_obj, m, null, type, mi, lookupPackMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
FinallyProcess:
|
|
||||||
il.Emit (OpCodes.Ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable var_writer, Variable var_obj, Variable var_loop, Func<Type, MethodInfo> lookupPackMethod)
|
|
||||||
{
|
|
||||||
Type et = t.GetElementType ();
|
|
||||||
il.EmitLd (var_writer, var_obj);
|
|
||||||
il.Emit (OpCodes.Ldlen);
|
|
||||||
il.Emit (OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteArrayHeader", new Type[]{ typeof(int) }));
|
|
||||||
|
|
||||||
Label beginLabel = il.DefineLabel ();
|
|
||||||
Label exprLabel = il.DefineLabel ();
|
|
||||||
|
|
||||||
// for-loop: init loop counter
|
|
||||||
il.EmitLdc (0);
|
|
||||||
il.EmitSt (var_loop);
|
|
||||||
|
|
||||||
// jump
|
|
||||||
il.Emit (OpCodes.Br_S, exprLabel);
|
|
||||||
|
|
||||||
// mark begin-label
|
|
||||||
il.MarkLabel (beginLabel);
|
|
||||||
|
|
||||||
// write element
|
|
||||||
EmitPackMemberValueCode (et, il, var_writer, var_obj, null, var_loop, t, mi, lookupPackMethod);
|
|
||||||
|
|
||||||
// increment loop-counter
|
|
||||||
il.EmitLd (var_loop);
|
|
||||||
il.Emit (OpCodes.Ldc_I4_1);
|
|
||||||
il.Emit (OpCodes.Add);
|
|
||||||
il.EmitSt (var_loop);
|
|
||||||
|
|
||||||
// mark expression label
|
|
||||||
il.MarkLabel (exprLabel);
|
|
||||||
|
|
||||||
// expression
|
|
||||||
il.EmitLd (var_loop, var_obj);
|
|
||||||
il.Emit (OpCodes.Ldlen);
|
|
||||||
il.Emit (OpCodes.Blt_S, beginLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <param name="m">(optional)</param>
|
|
||||||
/// <param name="elementIdx">(optional)</param>
|
|
||||||
static void EmitPackMemberValueCode (Type type, ILGenerator il, Variable var_writer, Variable var_obj,
|
|
||||||
MemberInfo m, Variable elementIdx, Type currentType, MethodInfo currentMethod, Func<Type, MethodInfo> lookupPackMethod)
|
|
||||||
{
|
|
||||||
MethodInfo mi;
|
|
||||||
il.EmitLd (var_writer, var_obj);
|
|
||||||
if (m != null)
|
|
||||||
il.EmitLdMember (m);
|
|
||||||
if (elementIdx != null) {
|
|
||||||
il.EmitLd (elementIdx);
|
|
||||||
il.Emit (OpCodes.Ldelem, type);
|
|
||||||
}
|
|
||||||
if (type.IsPrimitive) {
|
|
||||||
mi = typeof(MsgPackWriter).GetMethod("Write", new Type[]{type});
|
|
||||||
} else {
|
|
||||||
if (currentType == type) {
|
|
||||||
mi = currentMethod;
|
|
||||||
} else {
|
|
||||||
mi = lookupPackMethod (type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
il.Emit (OpCodes.Call, mi);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Unpack IL Generator
|
|
||||||
public static void EmitUnpackCode (Type type, MethodInfo mi, ILGenerator il,
|
|
||||||
Func<Type,MemberInfo[]> targetMemberSelector,
|
|
||||||
Func<MemberInfo,string> memberNameFormatter,
|
|
||||||
Func<Type, MethodInfo> lookupUnpackMethod,
|
|
||||||
Func<Type, IDictionary<string,int>> lookupMemberMapping,
|
|
||||||
MethodInfo lookupMemberMappingMethod)
|
|
||||||
{
|
|
||||||
if (type.IsArray) {
|
|
||||||
EmitUnpackArrayCode (type, mi, il, targetMemberSelector, memberNameFormatter, lookupUnpackMethod);
|
|
||||||
} else {
|
|
||||||
EmitUnpackMapCode (type, mi, il, targetMemberSelector, memberNameFormatter, lookupUnpackMethod, lookupMemberMapping, lookupMemberMappingMethod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EmitUnpackMapCode (Type type, MethodInfo mi, ILGenerator il,
|
|
||||||
Func<Type,MemberInfo[]> targetMemberSelector,
|
|
||||||
Func<MemberInfo,string> memberNameFormatter,
|
|
||||||
Func<Type, MethodInfo> lookupUnpackMethod,
|
|
||||||
Func<Type, IDictionary<string,int>> lookupMemberMapping,
|
|
||||||
MethodInfo lookupMemberMappingMethod)
|
|
||||||
{
|
|
||||||
MethodInfo failedMethod = typeof (PackILGenerator).GetMethod ("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
MemberInfo[] members = targetMemberSelector (type);
|
|
||||||
IDictionary<string, int> member_mapping = lookupMemberMapping (type);
|
|
||||||
for (int i = 0; i < members.Length; i ++)
|
|
||||||
member_mapping.Add (memberNameFormatter (members[i]), i);
|
|
||||||
|
|
||||||
Variable msgpackReader = Variable.CreateArg (0);
|
|
||||||
Variable obj = Variable.CreateLocal (il.DeclareLocal (type));
|
|
||||||
Variable num_of_fields = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
|
|
||||||
Variable loop_idx = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
|
|
||||||
Variable mapping = Variable.CreateLocal (il.DeclareLocal (typeof (IDictionary<string, int>)));
|
|
||||||
Variable switch_idx = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
|
|
||||||
Variable var_type = Variable.CreateLocal (il.DeclareLocal (typeof (Type)));
|
|
||||||
|
|
||||||
// if (!MsgPackReader.Read()) UnpackFailed ();
|
|
||||||
// if (MsgPackReader.Type == TypePrefixes.Nil) return null;
|
|
||||||
// if (!MsgPackReader.IsMap ()) UnpackFailed ();
|
|
||||||
EmitUnpackReadAndTypeCheckCode (il, msgpackReader, typeof (MsgPackReader).GetMethod ("IsMap"), failedMethod, true);
|
|
||||||
|
|
||||||
// type = typeof (T)
|
|
||||||
il.Emit (OpCodes.Ldtoken, type);
|
|
||||||
il.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle"));
|
|
||||||
il.EmitSt (var_type);
|
|
||||||
|
|
||||||
// mapping = LookupMemberMapping (typeof (T))
|
|
||||||
il.EmitLd (var_type);
|
|
||||||
il.Emit (OpCodes.Call, lookupMemberMappingMethod);
|
|
||||||
il.EmitSt (mapping);
|
|
||||||
|
|
||||||
// object o = FormatterServices.GetUninitializedObject (Type);
|
|
||||||
il.EmitLd (var_type);
|
|
||||||
il.Emit (OpCodes.Call, typeof (FormatterServices).GetMethod ("GetUninitializedObject"));
|
|
||||||
il.Emit (OpCodes.Castclass, type);
|
|
||||||
il.EmitSt (obj);
|
|
||||||
|
|
||||||
// num_of_fields = (int)reader.Length
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Length").GetGetMethod ());
|
|
||||||
il.EmitSt (num_of_fields);
|
|
||||||
|
|
||||||
// Loop labels
|
|
||||||
Label lblLoopStart = il.DefineLabel ();
|
|
||||||
Label lblLoopExpr = il.DefineLabel ();
|
|
||||||
|
|
||||||
// i = 0;
|
|
||||||
il.EmitLdc (0);
|
|
||||||
il.EmitSt (loop_idx);
|
|
||||||
il.Emit (OpCodes.Br, lblLoopExpr);
|
|
||||||
il.MarkLabel (lblLoopStart);
|
|
||||||
|
|
||||||
/* process */
|
|
||||||
// if (!MsgPackReader.Read() || !MsgPackReader.IsRaw()) UnpackFailed();
|
|
||||||
EmitUnpackReadAndTypeCheckCode (il, msgpackReader, typeof (MsgPackReader).GetMethod ("IsRaw"), failedMethod, false);
|
|
||||||
|
|
||||||
// MsgPackReader.ReadRawString ()
|
|
||||||
// if (!Dictionary.TryGetValue (,)) UnpackFailed();
|
|
||||||
Label lbl3 = il.DefineLabel ();
|
|
||||||
il.EmitLd (mapping);
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, typeof (MsgPackReader).GetMethod ("ReadRawString", new Type[0]));
|
|
||||||
il.Emit (OpCodes.Ldloca_S, (byte)switch_idx.Index);
|
|
||||||
il.Emit (OpCodes.Callvirt, typeof (IDictionary<string,int>).GetMethod ("TryGetValue"));
|
|
||||||
il.Emit (OpCodes.Brtrue, lbl3);
|
|
||||||
il.Emit (OpCodes.Call, failedMethod);
|
|
||||||
il.MarkLabel (lbl3);
|
|
||||||
|
|
||||||
// switch
|
|
||||||
Label[] switchCases = new Label[members.Length];
|
|
||||||
for (int i = 0; i < switchCases.Length; i ++)
|
|
||||||
switchCases[i] = il.DefineLabel ();
|
|
||||||
Label switchCaseEndLabel = il.DefineLabel ();
|
|
||||||
il.EmitLd (switch_idx);
|
|
||||||
il.Emit (OpCodes.Switch, switchCases);
|
|
||||||
il.Emit (OpCodes.Call, failedMethod);
|
|
||||||
|
|
||||||
for (int i = 0; i < switchCases.Length; i ++) {
|
|
||||||
il.MarkLabel (switchCases[i]);
|
|
||||||
MemberInfo minfo = members[i];
|
|
||||||
Type mt = minfo.GetMemberType ();
|
|
||||||
MethodInfo unpack_method = lookupUnpackMethod (mt);
|
|
||||||
il.EmitLd (obj);
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, unpack_method);
|
|
||||||
il.EmitStMember (minfo);
|
|
||||||
il.Emit (OpCodes.Br, switchCaseEndLabel);
|
|
||||||
}
|
|
||||||
il.MarkLabel (switchCaseEndLabel);
|
|
||||||
|
|
||||||
// i ++
|
|
||||||
il.EmitLd (loop_idx);
|
|
||||||
il.EmitLdc (1);
|
|
||||||
il.Emit (OpCodes.Add);
|
|
||||||
il.EmitSt (loop_idx);
|
|
||||||
|
|
||||||
// i < num_of_fields;
|
|
||||||
il.MarkLabel (lblLoopExpr);
|
|
||||||
il.EmitLd (loop_idx);
|
|
||||||
il.EmitLd (num_of_fields);
|
|
||||||
il.Emit (OpCodes.Blt, lblLoopStart);
|
|
||||||
|
|
||||||
// return
|
|
||||||
il.EmitLd (obj);
|
|
||||||
il.Emit (OpCodes.Ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EmitUnpackArrayCode (Type arrayType, MethodInfo mi, ILGenerator il,
|
|
||||||
Func<Type,MemberInfo[]> targetMemberSelector,
|
|
||||||
Func<MemberInfo,string> memberNameFormatter,
|
|
||||||
Func<Type, MethodInfo> lookupUnpackMethod)
|
|
||||||
{
|
|
||||||
Type elementType = arrayType.GetElementType ();
|
|
||||||
MethodInfo failedMethod = typeof (PackILGenerator).GetMethod ("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
Variable msgpackReader = Variable.CreateArg (0);
|
|
||||||
Variable obj = Variable.CreateLocal (il.DeclareLocal (arrayType));
|
|
||||||
Variable num_of_elements = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
|
|
||||||
Variable loop_idx = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
|
|
||||||
Variable type = Variable.CreateLocal (il.DeclareLocal (typeof (Type)));
|
|
||||||
|
|
||||||
// if (!MsgPackReader.Read() || !MsgPackReader.IsArray ()) UnpackFailed ();
|
|
||||||
EmitUnpackReadAndTypeCheckCode (il, msgpackReader, typeof (MsgPackReader).GetMethod ("IsArray"), failedMethod, true);
|
|
||||||
|
|
||||||
// type = typeof (T)
|
|
||||||
il.Emit (OpCodes.Ldtoken, elementType);
|
|
||||||
il.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle"));
|
|
||||||
il.EmitSt (type);
|
|
||||||
|
|
||||||
// num_of_elements = (int)reader.Length
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Length").GetGetMethod ());
|
|
||||||
il.EmitSt (num_of_elements);
|
|
||||||
|
|
||||||
// object o = Array.CreateInstance (Type, Length);
|
|
||||||
il.EmitLd (type);
|
|
||||||
il.EmitLd (num_of_elements);
|
|
||||||
il.Emit (OpCodes.Call, typeof (Array).GetMethod ("CreateInstance", new Type[] {typeof (Type), typeof (int)}));
|
|
||||||
il.Emit (OpCodes.Castclass, arrayType);
|
|
||||||
il.EmitSt (obj);
|
|
||||||
|
|
||||||
// Unpack element method
|
|
||||||
MethodInfo unpack_method = lookupUnpackMethod (elementType);
|
|
||||||
|
|
||||||
// Loop labels
|
|
||||||
Label lblLoopStart = il.DefineLabel ();
|
|
||||||
Label lblLoopExpr = il.DefineLabel ();
|
|
||||||
|
|
||||||
// i = 0;
|
|
||||||
il.EmitLdc (0);
|
|
||||||
il.EmitSt (loop_idx);
|
|
||||||
il.Emit (OpCodes.Br, lblLoopExpr);
|
|
||||||
il.MarkLabel (lblLoopStart);
|
|
||||||
|
|
||||||
/* process */
|
|
||||||
il.EmitLd (obj, loop_idx);
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, unpack_method);
|
|
||||||
il.Emit (OpCodes.Stelem, elementType);
|
|
||||||
|
|
||||||
// i ++
|
|
||||||
il.EmitLd (loop_idx);
|
|
||||||
il.EmitLdc (1);
|
|
||||||
il.Emit (OpCodes.Add);
|
|
||||||
il.EmitSt (loop_idx);
|
|
||||||
|
|
||||||
// i < num_of_fields;
|
|
||||||
il.MarkLabel (lblLoopExpr);
|
|
||||||
il.EmitLd (loop_idx);
|
|
||||||
il.EmitLd (num_of_elements);
|
|
||||||
il.Emit (OpCodes.Blt, lblLoopStart);
|
|
||||||
|
|
||||||
// return
|
|
||||||
il.EmitLd (obj);
|
|
||||||
il.Emit (OpCodes.Ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EmitUnpackReadAndTypeCheckCode (ILGenerator il, Variable msgpackReader, MethodInfo typeCheckMethod, MethodInfo failedMethod, bool nullCheckAndReturn)
|
|
||||||
{
|
|
||||||
Label lblFailed = il.DefineLabel ();
|
|
||||||
Label lblNullReturn = nullCheckAndReturn ? il.DefineLabel () : default(Label);
|
|
||||||
Label lblPassed = il.DefineLabel ();
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, typeof (MsgPackReader).GetMethod ("Read"));
|
|
||||||
il.Emit (OpCodes.Brfalse_S, lblFailed);
|
|
||||||
if (nullCheckAndReturn) {
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Type").GetGetMethod ());
|
|
||||||
il.EmitLdc ((int)TypePrefixes.Nil);
|
|
||||||
il.Emit (OpCodes.Beq_S, lblNullReturn);
|
|
||||||
}
|
|
||||||
il.EmitLd (msgpackReader);
|
|
||||||
il.Emit (OpCodes.Call, typeCheckMethod);
|
|
||||||
il.Emit (OpCodes.Brtrue_S, lblPassed);
|
|
||||||
il.Emit (OpCodes.Br, lblFailed);
|
|
||||||
if (nullCheckAndReturn) {
|
|
||||||
il.MarkLabel (lblNullReturn);
|
|
||||||
il.Emit (OpCodes.Ldnull);
|
|
||||||
il.Emit (OpCodes.Ret);
|
|
||||||
}
|
|
||||||
il.MarkLabel (lblFailed);
|
|
||||||
il.Emit (OpCodes.Call, failedMethod);
|
|
||||||
il.MarkLabel (lblPassed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Exception Helper</summary>
|
|
||||||
internal static void UnpackFailed ()
|
|
||||||
{
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Misc
|
|
||||||
static Type GetMemberType (this MemberInfo mi)
|
|
||||||
{
|
|
||||||
if (mi.MemberType == MemberTypes.Field)
|
|
||||||
return ((FieldInfo)mi).FieldType;
|
|
||||||
if (mi.MemberType == MemberTypes.Property)
|
|
||||||
return ((PropertyInfo)mi).PropertyType;
|
|
||||||
throw new ArgumentException ();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace MsgPack.Compiler
|
|
||||||
{
|
|
||||||
public class Variable
|
|
||||||
{
|
|
||||||
Variable (VariableType type, int index)
|
|
||||||
{
|
|
||||||
this.VarType = type;
|
|
||||||
this.Index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Variable CreateLocal (LocalBuilder local)
|
|
||||||
{
|
|
||||||
return new Variable (VariableType.Local, local.LocalIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Variable CreateArg (int idx)
|
|
||||||
{
|
|
||||||
return new Variable (VariableType.Arg, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VariableType VarType { get; set; }
|
|
||||||
public int Index { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace MsgPack.Compiler
|
|
||||||
{
|
|
||||||
public enum VariableType
|
|
||||||
{
|
|
||||||
Local,
|
|
||||||
Arg
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectGuid>{E1809531-EC2A-4EA6-B0E8-CC815EDFAA2F}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>MsgPack</RootNamespace>
|
|
||||||
<AssemblyName>MsgPack</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
|
||||||
<Compile Include="BoxingPacker.cs" />
|
|
||||||
<Compile Include="CompiledPacker.cs" />
|
|
||||||
<Compile Include="Compiler\EmitExtensions.cs" />
|
|
||||||
<Compile Include="Compiler\PackILGenerator.cs" />
|
|
||||||
<Compile Include="Compiler\Variable.cs" />
|
|
||||||
<Compile Include="Compiler\VariableType.cs" />
|
|
||||||
<Compile Include="MsgPackReader.cs" />
|
|
||||||
<Compile Include="MsgPackWriter.cs" />
|
|
||||||
<Compile Include="ObjectPacker.cs" />
|
|
||||||
<Compile Include="ReflectionCache.cs" />
|
|
||||||
<Compile Include="ReflectionCacheEntry.cs" />
|
|
||||||
<Compile Include="TypePrefixes.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
@ -1,258 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public class MsgPackReader
|
|
||||||
{
|
|
||||||
Stream _strm;
|
|
||||||
byte[] _tmp0 = new byte[8];
|
|
||||||
byte[] _tmp1 = new byte[8];
|
|
||||||
|
|
||||||
Encoding _encoding = Encoding.UTF8;
|
|
||||||
Decoder _decoder = Encoding.UTF8.GetDecoder ();
|
|
||||||
byte[] _buf = new byte[64];
|
|
||||||
|
|
||||||
public MsgPackReader (Stream strm)
|
|
||||||
{
|
|
||||||
_strm = strm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypePrefixes Type { get; private set; }
|
|
||||||
|
|
||||||
public bool ValueBoolean { get; private set; }
|
|
||||||
public uint Length { get; private set; }
|
|
||||||
|
|
||||||
public uint ValueUnsigned { get; private set; }
|
|
||||||
public ulong ValueUnsigned64 { get; private set; }
|
|
||||||
|
|
||||||
public int ValueSigned { get; private set; }
|
|
||||||
public long ValueSigned64 { get; private set; }
|
|
||||||
|
|
||||||
public float ValueFloat { get; private set; }
|
|
||||||
public double ValueDouble { get; private set; }
|
|
||||||
|
|
||||||
public bool IsSigned ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.NegativeFixNum ||
|
|
||||||
this.Type == TypePrefixes.PositiveFixNum ||
|
|
||||||
this.Type == TypePrefixes.Int8 ||
|
|
||||||
this.Type == TypePrefixes.Int16 ||
|
|
||||||
this.Type == TypePrefixes.Int32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsBoolean ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.True || this.Type == TypePrefixes.False;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSigned64 ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.Int64;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsUnsigned ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.PositiveFixNum ||
|
|
||||||
this.Type == TypePrefixes.UInt8 ||
|
|
||||||
this.Type == TypePrefixes.UInt16 ||
|
|
||||||
this.Type == TypePrefixes.UInt32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsUnsigned64 ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.UInt64;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRaw ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.FixRaw || this.Type == TypePrefixes.Raw16 || this.Type == TypePrefixes.Raw32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsArray ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.FixArray || this.Type == TypePrefixes.Array16 || this.Type == TypePrefixes.Array32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsMap ()
|
|
||||||
{
|
|
||||||
return this.Type == TypePrefixes.FixMap || this.Type == TypePrefixes.Map16 || this.Type == TypePrefixes.Map32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Read ()
|
|
||||||
{
|
|
||||||
byte[] tmp0 = _tmp0, tmp1 = _tmp1;
|
|
||||||
int x = _strm.ReadByte ();
|
|
||||||
if (x < 0)
|
|
||||||
return false; // EOS
|
|
||||||
|
|
||||||
if (x >= 0x00 && x <= 0x7f) {
|
|
||||||
this.Type = TypePrefixes.PositiveFixNum;
|
|
||||||
} else if (x >= 0xe0 && x <= 0xff) {
|
|
||||||
this.Type = TypePrefixes.NegativeFixNum;
|
|
||||||
} else if (x >= 0xa0 && x <= 0xbf) {
|
|
||||||
this.Type = TypePrefixes.FixRaw;
|
|
||||||
} else if (x >= 0x90 && x <= 0x9f) {
|
|
||||||
this.Type = TypePrefixes.FixArray;
|
|
||||||
} else if (x >= 0x80 && x <= 0x8f) {
|
|
||||||
this.Type = TypePrefixes.FixMap;
|
|
||||||
} else {
|
|
||||||
this.Type = (TypePrefixes)x;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this.Type) {
|
|
||||||
case TypePrefixes.Nil:
|
|
||||||
break;
|
|
||||||
case TypePrefixes.False:
|
|
||||||
ValueBoolean = false;
|
|
||||||
break;
|
|
||||||
case TypePrefixes.True:
|
|
||||||
ValueBoolean = true;
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Float:
|
|
||||||
_strm.Read (tmp0, 0, 4);
|
|
||||||
if (BitConverter.IsLittleEndian) {
|
|
||||||
tmp1[0] = tmp0[3];
|
|
||||||
tmp1[1] = tmp0[2];
|
|
||||||
tmp1[2] = tmp0[1];
|
|
||||||
tmp1[3] = tmp0[0];
|
|
||||||
ValueFloat = BitConverter.ToSingle (tmp1, 0);
|
|
||||||
} else {
|
|
||||||
ValueFloat = BitConverter.ToSingle (tmp0, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Double:
|
|
||||||
_strm.Read (tmp0, 0, 8);
|
|
||||||
if (BitConverter.IsLittleEndian) {
|
|
||||||
tmp1[0] = tmp0[7];
|
|
||||||
tmp1[1] = tmp0[6];
|
|
||||||
tmp1[2] = tmp0[5];
|
|
||||||
tmp1[3] = tmp0[4];
|
|
||||||
tmp1[4] = tmp0[3];
|
|
||||||
tmp1[5] = tmp0[2];
|
|
||||||
tmp1[6] = tmp0[1];
|
|
||||||
tmp1[7] = tmp0[0];
|
|
||||||
ValueDouble = BitConverter.ToDouble (tmp1, 0);
|
|
||||||
} else {
|
|
||||||
ValueDouble = BitConverter.ToDouble (tmp0, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TypePrefixes.NegativeFixNum:
|
|
||||||
ValueSigned = (x & 0x1f) - 0x20;
|
|
||||||
break;
|
|
||||||
case TypePrefixes.PositiveFixNum:
|
|
||||||
ValueSigned = x & 0x7f;
|
|
||||||
ValueUnsigned = (uint)ValueSigned;
|
|
||||||
break;
|
|
||||||
case TypePrefixes.UInt8:
|
|
||||||
x = _strm.ReadByte ();
|
|
||||||
if (x < 0)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueUnsigned = (uint)x;
|
|
||||||
break;
|
|
||||||
case TypePrefixes.UInt16:
|
|
||||||
if (_strm.Read (tmp0, 0, 2) != 2)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueUnsigned = ((uint)tmp0[0] << 8) | (uint)tmp0[1];
|
|
||||||
break;
|
|
||||||
case TypePrefixes.UInt32:
|
|
||||||
if (_strm.Read (tmp0, 0, 4) != 4)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueUnsigned = ((uint)tmp0[0] << 24) | ((uint)tmp0[1] << 16) | ((uint)tmp0[2] << 8) | (uint)tmp0[3];
|
|
||||||
break;
|
|
||||||
case TypePrefixes.UInt64:
|
|
||||||
if (_strm.Read (tmp0, 0, 8) != 8)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueUnsigned64 = ((ulong)tmp0[0] << 56) | ((ulong)tmp0[1] << 48) | ((ulong)tmp0[2] << 40) | ((ulong)tmp0[3] << 32) | ((ulong)tmp0[4] << 24) | ((ulong)tmp0[5] << 16) | ((ulong)tmp0[6] << 8) | (ulong)tmp0[7];
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Int8:
|
|
||||||
x = _strm.ReadByte ();
|
|
||||||
if (x < 0)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueSigned = (sbyte)x;
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Int16:
|
|
||||||
if (_strm.Read (tmp0, 0, 2) != 2)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueSigned = (short)((tmp0[0] << 8) | tmp0[1]);
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Int32:
|
|
||||||
if (_strm.Read (tmp0, 0, 4) != 4)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueSigned = (tmp0[0] << 24) | (tmp0[1] << 16) | (tmp0[2] << 8) | tmp0[3];
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Int64:
|
|
||||||
if (_strm.Read (tmp0, 0, 8) != 8)
|
|
||||||
throw new FormatException ();
|
|
||||||
ValueSigned64 = ((long)tmp0[0] << 56) | ((long)tmp0[1] << 48) | ((long)tmp0[2] << 40) | ((long)tmp0[3] << 32) | ((long)tmp0[4] << 24) | ((long)tmp0[5] << 16) | ((long)tmp0[6] << 8) | (long)tmp0[7];
|
|
||||||
break;
|
|
||||||
case TypePrefixes.FixRaw:
|
|
||||||
Length = (uint)(x & 0x1f);
|
|
||||||
break;
|
|
||||||
case TypePrefixes.FixArray:
|
|
||||||
case TypePrefixes.FixMap:
|
|
||||||
Length = (uint)(x & 0xf);
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Raw16:
|
|
||||||
case TypePrefixes.Array16:
|
|
||||||
case TypePrefixes.Map16:
|
|
||||||
if (_strm.Read (tmp0, 0, 2) != 2)
|
|
||||||
throw new FormatException ();
|
|
||||||
Length = ((uint)tmp0[0] << 8) | (uint)tmp0[1];
|
|
||||||
break;
|
|
||||||
case TypePrefixes.Raw32:
|
|
||||||
case TypePrefixes.Array32:
|
|
||||||
case TypePrefixes.Map32:
|
|
||||||
if (_strm.Read (tmp0, 0, 4) != 4)
|
|
||||||
throw new FormatException ();
|
|
||||||
Length = ((uint)tmp0[0] << 24) | ((uint)tmp0[1] << 16) | ((uint)tmp0[2] << 8) | (uint)tmp0[3];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadValueRaw (byte[] buf, int offset, int count)
|
|
||||||
{
|
|
||||||
return _strm.Read (buf, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadRawString ()
|
|
||||||
{
|
|
||||||
return ReadRawString (_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe string ReadRawString (byte[] buf)
|
|
||||||
{
|
|
||||||
if (this.Length < buf.Length) {
|
|
||||||
if (ReadValueRaw (buf, 0, (int)this.Length) != this.Length)
|
|
||||||
throw new FormatException ();
|
|
||||||
return _encoding.GetString (buf, 0, (int)this.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poor implementation
|
|
||||||
byte[] tmp = new byte[(int)this.Length];
|
|
||||||
if (ReadValueRaw (tmp, 0, tmp.Length) != tmp.Length)
|
|
||||||
throw new FormatException ();
|
|
||||||
return _encoding.GetString (tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,315 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public class MsgPackWriter
|
|
||||||
{
|
|
||||||
Stream _strm;
|
|
||||||
Encoding _encoding = Encoding.UTF8;
|
|
||||||
Encoder _encoder = Encoding.UTF8.GetEncoder ();
|
|
||||||
byte[] _tmp = new byte[9];
|
|
||||||
byte[] _buf = new byte[64];
|
|
||||||
|
|
||||||
public MsgPackWriter (Stream strm)
|
|
||||||
{
|
|
||||||
_strm = strm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (byte x)
|
|
||||||
{
|
|
||||||
if (x < 128) {
|
|
||||||
_strm.WriteByte (x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xcc;
|
|
||||||
tmp[1] = x;
|
|
||||||
_strm.Write (tmp, 0, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (ushort x)
|
|
||||||
{
|
|
||||||
if (x < 0x100) {
|
|
||||||
Write ((byte)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xcd;
|
|
||||||
tmp[1] = (byte)(x >> 8);
|
|
||||||
tmp[2] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (char x)
|
|
||||||
{
|
|
||||||
Write ((ushort)x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (uint x)
|
|
||||||
{
|
|
||||||
if (x < 0x10000) {
|
|
||||||
Write ((ushort)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xce;
|
|
||||||
tmp[1] = (byte)(x >> 24);
|
|
||||||
tmp[2] = (byte)(x >> 16);
|
|
||||||
tmp[3] = (byte)(x >> 8);
|
|
||||||
tmp[4] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (ulong x)
|
|
||||||
{
|
|
||||||
if (x < 0x100000000) {
|
|
||||||
Write ((uint)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xcf;
|
|
||||||
tmp[1] = (byte)(x >> 56);
|
|
||||||
tmp[2] = (byte)(x >> 48);
|
|
||||||
tmp[3] = (byte)(x >> 40);
|
|
||||||
tmp[4] = (byte)(x >> 32);
|
|
||||||
tmp[5] = (byte)(x >> 24);
|
|
||||||
tmp[6] = (byte)(x >> 16);
|
|
||||||
tmp[7] = (byte)(x >> 8);
|
|
||||||
tmp[8] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (sbyte x)
|
|
||||||
{
|
|
||||||
if (x >= -32 && x <= -1) {
|
|
||||||
_strm.WriteByte ((byte)(0xe0 | (byte)x));
|
|
||||||
} else if (x >= 0 && x <= 127) {
|
|
||||||
_strm.WriteByte ((byte)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xd0;
|
|
||||||
tmp[1] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (short x)
|
|
||||||
{
|
|
||||||
if (x >= sbyte.MinValue && x <= sbyte.MaxValue) {
|
|
||||||
Write ((sbyte)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xd1;
|
|
||||||
tmp[1] = (byte)(x >> 8);
|
|
||||||
tmp[2] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (int x)
|
|
||||||
{
|
|
||||||
if (x >= short.MinValue && x <= short.MaxValue) {
|
|
||||||
Write ((short)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xd2;
|
|
||||||
tmp[1] = (byte)(x >> 24);
|
|
||||||
tmp[2] = (byte)(x >> 16);
|
|
||||||
tmp[3] = (byte)(x >> 8);
|
|
||||||
tmp[4] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (long x)
|
|
||||||
{
|
|
||||||
if (x >= int.MinValue && x <= int.MaxValue) {
|
|
||||||
Write ((int)x);
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
tmp[0] = 0xd3;
|
|
||||||
tmp[1] = (byte)(x >> 56);
|
|
||||||
tmp[2] = (byte)(x >> 48);
|
|
||||||
tmp[3] = (byte)(x >> 40);
|
|
||||||
tmp[4] = (byte)(x >> 32);
|
|
||||||
tmp[5] = (byte)(x >> 24);
|
|
||||||
tmp[6] = (byte)(x >> 16);
|
|
||||||
tmp[7] = (byte)(x >> 8);
|
|
||||||
tmp[8] = (byte)x;
|
|
||||||
_strm.Write (tmp, 0, 9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteNil ()
|
|
||||||
{
|
|
||||||
_strm.WriteByte (0xc0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (bool x)
|
|
||||||
{
|
|
||||||
_strm.WriteByte ((byte)(x ? 0xc3 : 0xc2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (float x)
|
|
||||||
{
|
|
||||||
byte[] raw = BitConverter.GetBytes (x); // unsafeコードを使う?
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
|
|
||||||
tmp[0] = 0xca;
|
|
||||||
if (BitConverter.IsLittleEndian) {
|
|
||||||
tmp[1] = raw[3];
|
|
||||||
tmp[2] = raw[2];
|
|
||||||
tmp[3] = raw[1];
|
|
||||||
tmp[4] = raw[0];
|
|
||||||
} else {
|
|
||||||
tmp[1] = raw[0];
|
|
||||||
tmp[2] = raw[1];
|
|
||||||
tmp[3] = raw[2];
|
|
||||||
tmp[4] = raw[3];
|
|
||||||
}
|
|
||||||
_strm.Write (tmp, 0, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (double x)
|
|
||||||
{
|
|
||||||
byte[] raw = BitConverter.GetBytes (x); // unsafeコードを使う?
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
|
|
||||||
tmp[0] = 0xcb;
|
|
||||||
if (BitConverter.IsLittleEndian) {
|
|
||||||
tmp[1] = raw[7];
|
|
||||||
tmp[2] = raw[6];
|
|
||||||
tmp[3] = raw[5];
|
|
||||||
tmp[4] = raw[4];
|
|
||||||
tmp[5] = raw[3];
|
|
||||||
tmp[6] = raw[2];
|
|
||||||
tmp[7] = raw[1];
|
|
||||||
tmp[8] = raw[0];
|
|
||||||
} else {
|
|
||||||
tmp[1] = raw[0];
|
|
||||||
tmp[2] = raw[1];
|
|
||||||
tmp[3] = raw[2];
|
|
||||||
tmp[4] = raw[3];
|
|
||||||
tmp[5] = raw[4];
|
|
||||||
tmp[6] = raw[5];
|
|
||||||
tmp[7] = raw[6];
|
|
||||||
tmp[8] = raw[7];
|
|
||||||
}
|
|
||||||
_strm.Write (tmp, 0, 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (byte[] bytes)
|
|
||||||
{
|
|
||||||
WriteRawHeader (bytes.Length);
|
|
||||||
_strm.Write (bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteRawHeader (int N)
|
|
||||||
{
|
|
||||||
WriteLengthHeader (N, 32, 0xa0, 0xda, 0xdb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteArrayHeader (int N)
|
|
||||||
{
|
|
||||||
WriteLengthHeader (N, 16, 0x90, 0xdc, 0xdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteMapHeader (int N)
|
|
||||||
{
|
|
||||||
WriteLengthHeader (N, 16, 0x80, 0xde, 0xdf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteLengthHeader (int N, int fix_length, byte fix_prefix, byte len16bit_prefix, byte len32bit_prefix)
|
|
||||||
{
|
|
||||||
if (N < fix_length) {
|
|
||||||
_strm.WriteByte ((byte)(fix_prefix | N));
|
|
||||||
} else {
|
|
||||||
byte[] tmp = _tmp;
|
|
||||||
int header_len;
|
|
||||||
if (N < 0x10000) {
|
|
||||||
tmp[0] = len16bit_prefix;
|
|
||||||
tmp[1] = (byte)(N >> 8);
|
|
||||||
tmp[2] = (byte)N;
|
|
||||||
header_len = 3;
|
|
||||||
} else {
|
|
||||||
tmp[0] = len32bit_prefix;
|
|
||||||
tmp[1] = (byte)(N >> 24);
|
|
||||||
tmp[2] = (byte)(N >> 16);
|
|
||||||
tmp[3] = (byte)(N >> 8);
|
|
||||||
tmp[4] = (byte)N;
|
|
||||||
header_len = 5;
|
|
||||||
}
|
|
||||||
_strm.Write (tmp, 0, header_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (string x)
|
|
||||||
{
|
|
||||||
Write (x, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (string x, bool highProbAscii)
|
|
||||||
{
|
|
||||||
Write (x, _buf, highProbAscii);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write (string x, byte[] buf)
|
|
||||||
{
|
|
||||||
Write (x, buf, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe void Write (string x, byte[] buf, bool highProbAscii)
|
|
||||||
{
|
|
||||||
Encoder encoder = _encoder;
|
|
||||||
fixed (char *pstr = x)
|
|
||||||
fixed (byte *pbuf = buf) {
|
|
||||||
if (highProbAscii && x.Length <= buf.Length) {
|
|
||||||
bool isAsciiFullCompatible = true;
|
|
||||||
for (int i = 0; i < x.Length; i ++) {
|
|
||||||
int v = (int)pstr[i];
|
|
||||||
if (v > 0x7f) {
|
|
||||||
isAsciiFullCompatible = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf[i] = (byte)v;
|
|
||||||
}
|
|
||||||
if (isAsciiFullCompatible) {
|
|
||||||
WriteRawHeader (x.Length);
|
|
||||||
_strm.Write (buf, 0, x.Length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteRawHeader (encoder.GetByteCount (pstr, x.Length, true));
|
|
||||||
int str_len = x.Length;
|
|
||||||
char *p = pstr;
|
|
||||||
int convertedChars, bytesUsed;
|
|
||||||
bool completed = true;
|
|
||||||
while (str_len > 0 || !completed) {
|
|
||||||
encoder.Convert (p, str_len, pbuf, buf.Length, false, out convertedChars, out bytesUsed, out completed);
|
|
||||||
_strm.Write (buf, 0, bytesUsed);
|
|
||||||
str_len -= convertedChars;
|
|
||||||
p += convertedChars;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,259 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Runtime.Serialization;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public class ObjectPacker
|
|
||||||
{
|
|
||||||
byte[] _buf = new byte[64];
|
|
||||||
Encoding _encoding = Encoding.UTF8;
|
|
||||||
static Dictionary<Type, PackDelegate> PackerMapping;
|
|
||||||
static Dictionary<Type, UnpackDelegate> UnpackerMapping;
|
|
||||||
|
|
||||||
delegate void PackDelegate (ObjectPacker packer, MsgPackWriter writer, object o);
|
|
||||||
delegate object UnpackDelegate (ObjectPacker packer, MsgPackReader reader);
|
|
||||||
|
|
||||||
static ObjectPacker ()
|
|
||||||
{
|
|
||||||
PackerMapping = new Dictionary<Type, PackDelegate> ();
|
|
||||||
UnpackerMapping = new Dictionary<Type, UnpackDelegate> ();
|
|
||||||
|
|
||||||
PackerMapping.Add (typeof (string), StringPacker);
|
|
||||||
UnpackerMapping.Add (typeof (string), StringUnpacker);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Pack (object o)
|
|
||||||
{
|
|
||||||
using (MemoryStream ms = new MemoryStream ()) {
|
|
||||||
Pack (ms, o);
|
|
||||||
return ms.ToArray ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Pack (Stream strm, object o)
|
|
||||||
{
|
|
||||||
if (o != null && o.GetType ().IsPrimitive)
|
|
||||||
throw new NotSupportedException ();
|
|
||||||
MsgPackWriter writer = new MsgPackWriter (strm);
|
|
||||||
Pack (writer, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Pack (MsgPackWriter writer, object o)
|
|
||||||
{
|
|
||||||
if (o == null) {
|
|
||||||
writer.WriteNil ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type t = o.GetType ();
|
|
||||||
if (t.IsPrimitive) {
|
|
||||||
if (t.Equals (typeof (int))) writer.Write ((int)o);
|
|
||||||
else if (t.Equals (typeof (uint))) writer.Write ((uint)o);
|
|
||||||
else if (t.Equals (typeof (float))) writer.Write ((float)o);
|
|
||||||
else if (t.Equals (typeof (double))) writer.Write ((double)o);
|
|
||||||
else if (t.Equals (typeof (long))) writer.Write ((long)o);
|
|
||||||
else if (t.Equals (typeof (ulong))) writer.Write ((ulong)o);
|
|
||||||
else if (t.Equals (typeof (bool))) writer.Write ((bool)o);
|
|
||||||
else if (t.Equals (typeof (byte))) writer.Write ((byte)o);
|
|
||||||
else if (t.Equals (typeof (sbyte))) writer.Write ((sbyte)o);
|
|
||||||
else if (t.Equals (typeof (short))) writer.Write ((short)o);
|
|
||||||
else if (t.Equals (typeof (ushort))) writer.Write ((ushort)o);
|
|
||||||
else if (t.Equals (typeof (char))) writer.Write ((ushort)(char)o);
|
|
||||||
else throw new NotSupportedException ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackDelegate packer;
|
|
||||||
if (PackerMapping.TryGetValue (t, out packer)) {
|
|
||||||
packer (this, writer, o);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.IsArray) {
|
|
||||||
Array ary = (Array)o;
|
|
||||||
writer.WriteArrayHeader (ary.Length);
|
|
||||||
for (int i = 0; i < ary.Length; i ++)
|
|
||||||
Pack (writer, ary.GetValue (i));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReflectionCacheEntry entry = ReflectionCache.Lookup (t);
|
|
||||||
writer.WriteMapHeader (entry.FieldMap.Count);
|
|
||||||
foreach (KeyValuePair<string, FieldInfo> pair in entry.FieldMap) {
|
|
||||||
writer.Write (pair.Key, _buf);
|
|
||||||
object v = pair.Value.GetValue (o);
|
|
||||||
if (pair.Value.FieldType.IsInterface && v != null) {
|
|
||||||
writer.WriteArrayHeader (2);
|
|
||||||
writer.Write (v.GetType().FullName);
|
|
||||||
}
|
|
||||||
Pack (writer, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (typeof (T).IsPrimitive)
|
|
||||||
throw new NotSupportedException ();
|
|
||||||
MsgPackReader reader = new MsgPackReader (strm);
|
|
||||||
return (T)Unpack (reader, typeof (T));
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Unpack (Type type, byte[] buf)
|
|
||||||
{
|
|
||||||
return Unpack (type, buf, 0, buf.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Unpack (Type type, byte[] buf, int offset, int size)
|
|
||||||
{
|
|
||||||
using (MemoryStream ms = new MemoryStream (buf, offset, size)) {
|
|
||||||
return Unpack (type, ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Unpack (Type type, Stream strm)
|
|
||||||
{
|
|
||||||
if (type.IsPrimitive)
|
|
||||||
throw new NotSupportedException ();
|
|
||||||
MsgPackReader reader = new MsgPackReader (strm);
|
|
||||||
return Unpack (reader, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
object Unpack (MsgPackReader reader, Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive) {
|
|
||||||
if (!reader.Read ()) throw new FormatException ();
|
|
||||||
if (t.Equals (typeof (int)) && reader.IsSigned ()) return reader.ValueSigned;
|
|
||||||
else if (t.Equals (typeof (uint)) && reader.IsUnsigned ()) return reader.ValueUnsigned;
|
|
||||||
else if (t.Equals (typeof (float)) && reader.Type == TypePrefixes.Float) return reader.ValueFloat;
|
|
||||||
else if (t.Equals (typeof (double)) && reader.Type == TypePrefixes.Double) return reader.ValueDouble;
|
|
||||||
else if (t.Equals (typeof (long))) {
|
|
||||||
if (reader.IsSigned64 ())
|
|
||||||
return reader.ValueSigned64;
|
|
||||||
if (reader.IsSigned ())
|
|
||||||
return (long)reader.ValueSigned;
|
|
||||||
} else if (t.Equals (typeof (ulong))) {
|
|
||||||
if (reader.IsUnsigned64 ())
|
|
||||||
return reader.ValueUnsigned64;
|
|
||||||
if (reader.IsUnsigned ())
|
|
||||||
return (ulong)reader.ValueUnsigned;
|
|
||||||
} else if (t.Equals (typeof (bool)) && reader.IsBoolean ()) return (reader.Type == TypePrefixes.True);
|
|
||||||
else if (t.Equals (typeof (byte)) && reader.IsUnsigned ()) return (byte)reader.ValueUnsigned;
|
|
||||||
else if (t.Equals (typeof (sbyte)) && reader.IsSigned ()) return (sbyte)reader.ValueSigned;
|
|
||||||
else if (t.Equals (typeof (short)) && reader.IsSigned ()) return (short)reader.ValueSigned;
|
|
||||||
else if (t.Equals (typeof (ushort)) && reader.IsUnsigned ()) return (ushort)reader.ValueUnsigned;
|
|
||||||
else if (t.Equals (typeof (char)) && reader.IsUnsigned ()) return (char)reader.ValueUnsigned;
|
|
||||||
else throw new NotSupportedException ();
|
|
||||||
}
|
|
||||||
|
|
||||||
UnpackDelegate unpacker;
|
|
||||||
if (UnpackerMapping.TryGetValue (t, out unpacker))
|
|
||||||
return unpacker (this, reader);
|
|
||||||
|
|
||||||
if (t.IsArray) {
|
|
||||||
if (!reader.Read () || (!reader.IsArray () && reader.Type != TypePrefixes.Nil))
|
|
||||||
throw new FormatException ();
|
|
||||||
if (reader.Type == TypePrefixes.Nil)
|
|
||||||
return null;
|
|
||||||
Type et = t.GetElementType ();
|
|
||||||
Array ary = Array.CreateInstance (et, (int)reader.Length);
|
|
||||||
for (int i = 0; i < ary.Length; i ++)
|
|
||||||
ary.SetValue (Unpack (reader, et), i);
|
|
||||||
return ary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!reader.Read ())
|
|
||||||
throw new FormatException ();
|
|
||||||
if (reader.Type == TypePrefixes.Nil)
|
|
||||||
return null;
|
|
||||||
if (t.IsInterface) {
|
|
||||||
if (reader.Type != TypePrefixes.FixArray && reader.Length != 2)
|
|
||||||
throw new FormatException ();
|
|
||||||
if (!reader.Read () || !reader.IsRaw ())
|
|
||||||
throw new FormatException ();
|
|
||||||
CheckBufferSize ((int)reader.Length);
|
|
||||||
reader.ReadValueRaw (_buf, 0, (int)reader.Length);
|
|
||||||
t = Type.GetType (Encoding.UTF8.GetString (_buf, 0, (int)reader.Length));
|
|
||||||
if (!reader.Read () || reader.Type == TypePrefixes.Nil)
|
|
||||||
throw new FormatException ();
|
|
||||||
}
|
|
||||||
if (!reader.IsMap ())
|
|
||||||
throw new FormatException ();
|
|
||||||
|
|
||||||
object o = FormatterServices.GetUninitializedObject (t);
|
|
||||||
ReflectionCacheEntry entry = ReflectionCache.Lookup (t);
|
|
||||||
int members = (int)reader.Length;
|
|
||||||
for (int i = 0; i < members; i ++) {
|
|
||||||
if (!reader.Read () || !reader.IsRaw ())
|
|
||||||
throw new FormatException ();
|
|
||||||
CheckBufferSize ((int)reader.Length);
|
|
||||||
reader.ReadValueRaw (_buf, 0, (int)reader.Length);
|
|
||||||
string name = Encoding.UTF8.GetString (_buf, 0, (int)reader.Length);
|
|
||||||
FieldInfo f;
|
|
||||||
if (!entry.FieldMap.TryGetValue (name, out f))
|
|
||||||
throw new FormatException ();
|
|
||||||
f.SetValue (o, Unpack (reader, f.FieldType));
|
|
||||||
}
|
|
||||||
|
|
||||||
IDeserializationCallback callback = o as IDeserializationCallback;
|
|
||||||
if (callback != null)
|
|
||||||
callback.OnDeserialization (this);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckBufferSize (int size)
|
|
||||||
{
|
|
||||||
if (_buf.Length < size)
|
|
||||||
Array.Resize<byte> (ref _buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StringPacker (ObjectPacker packer, MsgPackWriter writer, object o)
|
|
||||||
{
|
|
||||||
writer.Write (Encoding.UTF8.GetBytes ((string)o));
|
|
||||||
}
|
|
||||||
|
|
||||||
static object StringUnpacker (ObjectPacker packer, MsgPackReader reader)
|
|
||||||
{
|
|
||||||
if (!reader.Read ())
|
|
||||||
throw new FormatException ();
|
|
||||||
if (reader.Type == TypePrefixes.Nil)
|
|
||||||
return null;
|
|
||||||
if (!reader.IsRaw ())
|
|
||||||
throw new FormatException ();
|
|
||||||
packer.CheckBufferSize ((int)reader.Length);
|
|
||||||
reader.ReadValueRaw (packer._buf, 0, (int)reader.Length);
|
|
||||||
return Encoding.UTF8.GetString (packer._buf, 0, (int)reader.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public static class ReflectionCache
|
|
||||||
{
|
|
||||||
static Dictionary<Type, ReflectionCacheEntry> _cache;
|
|
||||||
|
|
||||||
static ReflectionCache ()
|
|
||||||
{
|
|
||||||
_cache = new Dictionary<Type,ReflectionCacheEntry> ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ReflectionCacheEntry Lookup (Type type)
|
|
||||||
{
|
|
||||||
ReflectionCacheEntry entry;
|
|
||||||
lock (_cache) {
|
|
||||||
if (_cache.TryGetValue (type, out entry))
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = new ReflectionCacheEntry (type);
|
|
||||||
lock (_cache) {
|
|
||||||
_cache[type] = entry;
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RemoveCache (Type type)
|
|
||||||
{
|
|
||||||
lock (_cache) {
|
|
||||||
_cache.Remove (type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Clear ()
|
|
||||||
{
|
|
||||||
lock (_cache) {
|
|
||||||
_cache.Clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.Reflection;
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public class ReflectionCacheEntry
|
|
||||||
{
|
|
||||||
const BindingFlags FieldBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.SetField;
|
|
||||||
|
|
||||||
public ReflectionCacheEntry (Type t)
|
|
||||||
{
|
|
||||||
FieldInfo[] fields = t.GetFields (FieldBindingFlags);
|
|
||||||
IDictionary<string, FieldInfo> map = new Dictionary<string, FieldInfo> (fields.Length);
|
|
||||||
for (int i = 0; i < fields.Length; i ++) {
|
|
||||||
FieldInfo f = fields[i];
|
|
||||||
string name = f.Name;
|
|
||||||
int pos;
|
|
||||||
if (name[0] == '<' && (pos = name.IndexOf ('>')) > 1)
|
|
||||||
name = name.Substring (1, pos - 1); // Auto-Property (\<.+\>) <ab>
|
|
||||||
map[name] = f;
|
|
||||||
}
|
|
||||||
FieldMap = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDictionary<string, FieldInfo> FieldMap { get; private set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace MsgPack
|
|
||||||
{
|
|
||||||
public enum TypePrefixes : byte
|
|
||||||
{
|
|
||||||
PositiveFixNum = 0x00, // 0x00 - 0x7f
|
|
||||||
NegativeFixNum = 0xe0, // 0xe0 - 0xff
|
|
||||||
|
|
||||||
Nil = 0xc0,
|
|
||||||
False = 0xc2,
|
|
||||||
True = 0xc3,
|
|
||||||
Float = 0xca,
|
|
||||||
Double = 0xcb,
|
|
||||||
UInt8 = 0xcc,
|
|
||||||
UInt16 = 0xcd,
|
|
||||||
UInt32 = 0xce,
|
|
||||||
UInt64 = 0xcf,
|
|
||||||
Int8 = 0xd0,
|
|
||||||
Int16 = 0xd1,
|
|
||||||
Int32 = 0xd2,
|
|
||||||
Int64 = 0xd3,
|
|
||||||
Raw16 = 0xda,
|
|
||||||
Raw32 = 0xdb,
|
|
||||||
Array16 = 0xdc,
|
|
||||||
Array32 = 0xdd,
|
|
||||||
Map16 = 0xde,
|
|
||||||
Map32 = 0xdf,
|
|
||||||
|
|
||||||
FixRaw = 0xa0, // 0xa0 - 0xbf
|
|
||||||
FixArray = 0x90, // 0x90 - 0x9f
|
|
||||||
FixMap = 0x80, // 0x80 - 0x8f
|
|
||||||
}
|
|
||||||
}
|
|
1
csharp/README.md
Normal file
1
csharp/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
MessagePack for C# was moved to https://github.com/msgpack/msgpack-cli.
|
Loading…
x
Reference in New Issue
Block a user