Skip to content

Commit

Permalink
- Added missing serialization support for byte, short, unshort
Browse files Browse the repository at this point in the history
- Added logic to detect correct underlying type for enum when de/serializing

Signed-off-by: rpgmaker <olamide.bakre@gmail.com>
  • Loading branch information
rpgmaker committed Nov 14, 2014
1 parent fe57bb6 commit 96c30e8
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 23 deletions.
Binary file modified NetJSON.v12.suo
Binary file not shown.
179 changes: 159 additions & 20 deletions NetJSON/NetJSON.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ private static class NetJSONCachedSerializer<T> {
_toExpectedType = typeof(AutomaticTypeConverter).GetMethod("ToExpectedType"),
_fastStringToInt = _jsonType.GetMethod("FastStringToInt", MethodBinding),
_fastStringToUInt = _jsonType.GetMethod("FastStringToUInt", MethodBinding),
_fastStringToUShort = _jsonType.GetMethod("FastStringToUShort", MethodBinding),
_fastStringToShort = _jsonType.GetMethod("FastStringToShort", MethodBinding),
_fastStringToByte = _jsonType.GetMethod("FastStringToByte", MethodBinding),
_fastStringToLong = _jsonType.GetMethod("FastStringToLong", MethodBinding),
_fastStringToULong = _jsonType.GetMethod("FastStringToULong", MethodBinding),
_fastStringToDecimal = _jsonType.GetMethod("FastStringToDecimal", MethodBinding),
Expand Down Expand Up @@ -981,17 +984,18 @@ internal static MethodInfo ReadStringToEnumFor(TypeBuilder typeBuilder, Type typ
method = typeBuilder.DefineMethod(methodName, StaticMethodAttribute,
type, new[] { _stringType });
_readEnumToStringMethodBuilders[key] = method;

var eType = type.GetEnumUnderlyingType();
var il = method.GetILGenerator();

var values = Enum.GetValues(type).Cast<int>().ToArray();
var values = Enum.GetValues(type).Cast<object>().ToArray();
var keys = Enum.GetNames(type);

for (var i = 0; i < values.Length; i++) {

var value = values[i];
var k = keys[i];
var @int = value;


var label = il.DefineLabel();
var label2 = il.DefineLabel();

Expand All @@ -1000,24 +1004,77 @@ internal static MethodInfo ReadStringToEnumFor(TypeBuilder typeBuilder, Type typ
il.Emit(OpCodes.Call, _stringOpEquality);
il.Emit(OpCodes.Brfalse, label);

il.Emit(OpCodes.Ldc_I4, @int);
if (eType == _intType)
il.Emit(OpCodes.Ldc_I4, (int)value);
else if (eType == _longType)
il.Emit(OpCodes.Ldc_I8, (long)value);
else if (eType == typeof(ulong))
il.Emit(OpCodes.Ldc_I8, (long)((ulong)value));
else if (eType == typeof(uint))
il.Emit(OpCodes.Ldc_I4, (uint)value);
else if (eType == typeof(byte)) {
il.Emit(OpCodes.Ldc_I4, (int)((byte)value));
il.Emit(OpCodes.Conv_U1);
} else if (eType == typeof(ushort)) {
il.Emit(OpCodes.Ldc_I4, (int)((ushort)value));
il.Emit(OpCodes.Conv_U2);
} else if (eType == typeof(short)) {
il.Emit(OpCodes.Ldc_I4, (int)((short)value));
il.Emit(OpCodes.Conv_I2);
}


il.Emit(OpCodes.Ret);

il.MarkLabel(label);

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldstr, IntToStr(@int));


if (eType == _intType)
il.Emit(OpCodes.Ldstr, IntToStr((int)value));
else if (eType == _longType)
il.Emit(OpCodes.Ldstr, LongToStr((long)value));
else if (eType == typeof(ulong))
il.Emit(OpCodes.Ldstr, IntUtility.ultoa((ulong)value));
else if (eType == typeof(uint))
il.Emit(OpCodes.Ldstr, IntUtility.uitoa((uint)value));
else if (eType == typeof(byte))
il.Emit(OpCodes.Ldstr, IntToStr((int)((byte)value)));
else if (eType == typeof(ushort))
il.Emit(OpCodes.Ldstr, IntToStr((int)((ushort)value)));
else if (eType == typeof(short))
il.Emit(OpCodes.Ldstr, IntToStr((int)((short)value)));

il.Emit(OpCodes.Call, _stringOpEquality);
il.Emit(OpCodes.Brfalse, label2);

il.Emit(OpCodes.Ldc_I4, @int);
if (eType == _intType)
il.Emit(OpCodes.Ldc_I4, (int)value);
else if (eType == _longType)
il.Emit(OpCodes.Ldc_I8, (long)value);
else if (eType == typeof(ulong))
il.Emit(OpCodes.Ldc_I8, (long)((ulong)value));
else if (eType == typeof(uint))
il.Emit(OpCodes.Ldc_I4, (uint)value);
else if (eType == typeof(byte)) {
il.Emit(OpCodes.Ldc_I4, (int)((byte)value));
il.Emit(OpCodes.Conv_U1);
} else if (eType == typeof(ushort)) {
il.Emit(OpCodes.Ldc_I4, (int)((ushort)value));
il.Emit(OpCodes.Conv_U2);
} else if (eType == typeof(short)) {
il.Emit(OpCodes.Ldc_I4, (int)((short)value));
il.Emit(OpCodes.Conv_I2);
}

il.Emit(OpCodes.Ret);

il.MarkLabel(label2);
}

//Return default enum if no match is found
il.Emit(OpCodes.Ldc_I4_0);
LoadDefaultValueByType(il, eType);
il.Emit(OpCodes.Ret);

return method;
Expand All @@ -1033,23 +1090,44 @@ internal static MethodInfo WriteEnumToStringFor(TypeBuilder typeBuilder, Type ty
method = typeBuilder.DefineMethod(methodName, StaticMethodAttribute,
_stringType, new[] { type });
_writeEnumToStringMethodBuilders[key] = method;

var eType = type.GetEnumUnderlyingType();

var il = method.GetILGenerator();

if (_useEnumString) {
var values = Enum.GetValues(type).Cast<int>().ToArray();
var values = Enum.GetValues(type).Cast<object>().ToArray();
var names = Enum.GetNames(type);

var count = values.Length;

for (var i = 0; i < count; i++) {

var value = values[i];
var @int = value;


var label = il.DefineLabel();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, @int);

if (eType == _intType)
il.Emit(OpCodes.Ldc_I4, (int)value);
else if (eType == _longType)
il.Emit(OpCodes.Ldc_I8, (long)value);
else if (eType == typeof(ulong))
il.Emit(OpCodes.Ldc_I8, (long)((ulong)value));
else if (eType == typeof(uint))
il.Emit(OpCodes.Ldc_I4, (uint)value);
else if (eType == typeof(byte)) {
il.Emit(OpCodes.Ldc_I4, (int)((byte)value));
il.Emit(OpCodes.Conv_U1);
} else if (eType == typeof(ushort)) {
il.Emit(OpCodes.Ldc_I4, (int)((ushort)value));
il.Emit(OpCodes.Conv_U2);
} else if (eType == typeof(short)) {
il.Emit(OpCodes.Ldc_I4, (int)((short)value));
il.Emit(OpCodes.Conv_I2);
}

il.Emit(OpCodes.Bne_Un, label);

il.Emit(OpCodes.Ldstr, names[i]);
Expand All @@ -1058,32 +1136,64 @@ internal static MethodInfo WriteEnumToStringFor(TypeBuilder typeBuilder, Type ty
il.MarkLabel(label);
}

il.Emit(OpCodes.Ldstr, "0");
} else {
var values = Enum.GetValues(type).Cast<int>().ToArray();
var values = Enum.GetValues(type).Cast<object>().ToArray();

var count = values.Length;

for (var i = 0; i < count; i++) {

var value = values[i];
var @int = value;


var label = il.DefineLabel();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, @int);

if (eType == _intType)
il.Emit(OpCodes.Ldc_I4, (int)value);
else if (eType == _longType)
il.Emit(OpCodes.Ldc_I8, (long)value);
else if (eType == typeof(ulong))
il.Emit(OpCodes.Ldc_I8, (long)((ulong)value));
else if (eType == typeof(uint))
il.Emit(OpCodes.Ldc_I4, (uint)value);
else if (eType == typeof(byte)) {
il.Emit(OpCodes.Ldc_I4, (int)((byte)value));
il.Emit(OpCodes.Conv_U1);
} else if (eType == typeof(ushort)) {
il.Emit(OpCodes.Ldc_I4, (int)((ushort)value));
il.Emit(OpCodes.Conv_U2);
} else if (eType == typeof(short)) {
il.Emit(OpCodes.Ldc_I4, (int)((short)value));
il.Emit(OpCodes.Conv_I2);
}

il.Emit(OpCodes.Bne_Un, label);

il.Emit(OpCodes.Ldstr, IntToStr(@int));
if (eType == _intType)
il.Emit(OpCodes.Ldstr, IntToStr((int)value));
else if (eType == _longType)
il.Emit(OpCodes.Ldstr, LongToStr((long)value));
else if (eType == typeof(ulong))
il.Emit(OpCodes.Ldstr, IntUtility.ultoa((ulong)value));
else if (eType == typeof(uint))
il.Emit(OpCodes.Ldstr, IntUtility.uitoa((uint)value));
else if (eType == typeof(byte))
il.Emit(OpCodes.Ldstr, IntToStr((int)((byte)value)));
else if (eType == typeof(ushort))
il.Emit(OpCodes.Ldstr, IntToStr((int)((ushort)value)));
else if (eType == typeof(short))
il.Emit(OpCodes.Ldstr, IntToStr((int)((short)value)));


il.Emit(OpCodes.Ret);

il.MarkLabel(label);
}

il.Emit(OpCodes.Ldstr, "0");
}


il.Emit(OpCodes.Ldstr, "0");

il.Emit(OpCodes.Ret);

Expand Down Expand Up @@ -1970,6 +2080,11 @@ internal static void WritePropertiesFor(TypeBuilder typeBuilder, Type type, ILGe
private static void LoadDefaultValueByType(ILGenerator il, Type type) {
if (type == _intType)
il.Emit(OpCodes.Ldc_I4_0);
else if(type == typeof(byte) || type == typeof(short) || type == typeof(ushort)){
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(typeof(byte) == type ? OpCodes.Conv_U1 :
typeof(short) == type ? OpCodes.Conv_I2 : OpCodes.Conv_U2);
}
else if (type == typeof(uint))
il.Emit(OpCodes.Ldc_I4_0);
else if (type == typeof(long))
Expand Down Expand Up @@ -2306,6 +2421,24 @@ public static bool IsValueDate(string value) {
return value.StartsWith("\\/Date") || _dateISORegex.IsMatch(value);
}

public static unsafe byte FastStringToByte(string str) {
unchecked {
return (byte)FastStringToInt(str);
}
}

public static unsafe short FastStringToShort(string str) {
unchecked {
return (short)FastStringToInt(str);
}
}

public static unsafe ushort FastStringToUShort(string str) {
unchecked {
return (ushort)FastStringToInt(str);
}
}

public static unsafe int FastStringToInt(string strNum) {
int val = 0;
int neg = 1;
Expand Down Expand Up @@ -2543,7 +2676,7 @@ private static MethodInfo GenerateExtractValueFor(TypeBuilder typeBuilder, Type
}

public static bool FastStringToBool(string value) {
return value == "1" || value.Equals("true", StringComparison.OrdinalIgnoreCase);
return value == "1" || String.Equals(value, "true", StringComparison.OrdinalIgnoreCase);
}

public static byte[] FastStringToByteArray(string value) {
Expand Down Expand Up @@ -2577,6 +2710,12 @@ private static void GenerateChangeTypeFor(TypeBuilder typeBuilder, Type type, IL

if (type == _intType)
il.Emit(OpCodes.Call, _fastStringToInt);
else if (type == typeof(short))
il.Emit(OpCodes.Call, _fastStringToShort);
else if (type == typeof(ushort))
il.Emit(OpCodes.Call, _fastStringToUShort);
else if (type == typeof(byte))
il.Emit(OpCodes.Call, _fastStringToByte);
else if (type == typeof(uint))
il.Emit(OpCodes.Call, _fastStringToUInt);
else if (type == _decimalType)
Expand Down
2 changes: 1 addition & 1 deletion NetJSON/NetJSON.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<id>NetJSON</id>
<title>NetJSON</title>
<tags>json json-serializer javascript JSON serializer binary</tags>
<version>1.0.5.1</version>
<version>1.0.5.2</version>
<authors>TJ Bakre</authors>
<description>Faster than Any Binary?</description>
<language>en-US</language>
Expand Down
4 changes: 2 additions & 2 deletions NetJSON/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.5.1")]
[assembly: AssemblyFileVersion("1.0.5.1")]
[assembly: AssemblyVersion("1.0.5.2")]
[assembly: AssemblyFileVersion("1.0.5.2")]
Binary file modified NetJSON/lib/net40/NetJSON.dll
Binary file not shown.

0 comments on commit 96c30e8

Please sign in to comment.