private static int BytesToRead(object i) { if (i is byte) { return(1); } bool size; ulong integer; if (i is decimal) { return(BytesToRead((int)dec_flags.GetValue(i)) + BytesToRead((int)dec_lo.GetValue(i)) + BytesToRead((int)dec_mid.GetValue(i)) + BytesToRead((int)dec_hi.GetValue(i))); } if ((size = i is float) || i is double) { int bytes = size ? 4 : 8; Array type_holder = size ? holder_f as Array : holder_d as Array; // Fetch the preallocated array Array result_holder = size ? holder_i as Array : holder_u as Array; lock (result_holder) lock (type_holder) { // Clear artifacts if (size) { result_holder.SetValue(0U, 0); } else { result_holder.SetValue(0UL, 0); } type_holder.SetValue(i, 0); // Insert the value to convert into the preallocated holder array Buffer.BlockCopy(type_holder, 0, result_holder, 0, bytes); // Perform an internal copy to the byte-based holder if (size) { integer = BinaryHelpers.SwapEndian((uint)result_holder.GetValue(0)); } else { integer = BinaryHelpers.SwapEndian((ulong)result_holder.GetValue(0)); } } } else { integer = i as ulong? ?? i as uint? ?? i as ushort? ?? i as byte? ?? 0; } return (integer <= 240 ? 1 : integer <= 2287 ? 2 : integer <= 67823 ? 3 : integer <= 16777215 ? 4 : integer <= 4294967295 ? 5 : integer <= 1099511627775 ? 6 : integer <= 281474976710655 ? 7 : integer <= 72057594037927935 ? 8 : 9); }
private T ReadFloating <T>() { int size = Marshal.SizeOf(typeof(T)); Array type_holder = size == 4 ? holder_f as Array : holder_d as Array; Array result_holder = size == 4 ? holder_i as Array : holder_u as Array; T result; lock (result_holder) lock (type_holder) { if (size == 4) { result_holder.SetValue(BinaryHelpers.SwapEndian(ReadUInt()), 0); } else { result_holder.SetValue(BinaryHelpers.SwapEndian(ReadULong()), 0); } Buffer.BlockCopy(result_holder, 0, type_holder, 0, size); result = (T)type_holder.GetValue(0); } return(result); }
private static void Serialize <T>(T t, byte[] writeTo, ref long bitOffset, ref bool isAligned) { Type type = t.GetType(); bool size = false; if (type.IsArray) { var array = t as Array; Serialize((uint)array.Length, writeTo, ref bitOffset, ref isAligned); foreach (var element in array) { Serialize(element, writeTo, ref bitOffset, ref isAligned); } } else if (type == typeof(Partial)) { byte count; WriteByte(writeTo, (byte)Partial.value_info.GetValue(t), bitOffset, isAligned, count = (byte)Partial.count_info.GetValue(t)); bitOffset += count; isAligned = bitOffset % 8 == 0; return; } else if (IsSupportedType(type)) { long offset = t is bool? 1 : BytesToRead(t) * 8; if (type == typeof(bool)) { WriteBit(writeTo, t as bool? ?? false, bitOffset); bitOffset += offset; isAligned = bitOffset % 8 == 0; } else if (type == typeof(decimal)) { WriteDynamic(writeTo, (int)dec_lo.GetValue(t), 4, bitOffset, isAligned); WriteDynamic(writeTo, (int)dec_mid.GetValue(t), 4, bitOffset + 32, isAligned); WriteDynamic(writeTo, (int)dec_hi.GetValue(t), 4, bitOffset + 64, isAligned); WriteDynamic(writeTo, (int)dec_flags.GetValue(t), 4, bitOffset + 96, isAligned); bitOffset += offset; } else if ((size = type == typeof(float)) || type == typeof(double)) { int bytes = size ? 4 : 8; Array type_holder = size ? holder_f as Array : holder_d as Array; // Fetch the preallocated array Array result_holder = size ? holder_i as Array : holder_u as Array; lock (result_holder) lock (type_holder) { // Clear artifacts if (size) { result_holder.SetValue(0U, 0); } else { result_holder.SetValue(0UL, 0); } type_holder.SetValue(t, 0); // Insert the value to convert into the preallocated holder array Buffer.BlockCopy(type_holder, 0, result_holder, 0, bytes); // Perform an internal copy to the byte-based holder // Since floating point flag bits are seemingly the highest bytes of the floating point values // and even very small values have them, we swap the endianness in the hopes of reducing the size if (size) { Serialize(BinaryHelpers.SwapEndian((uint)result_holder.GetValue(0)), writeTo, ref bitOffset, ref isAligned); } else { Serialize(BinaryHelpers.SwapEndian((ulong)result_holder.GetValue(0)), writeTo, ref bitOffset, ref isAligned); } } } else { ulong value; if (t is byte) { WriteByte(writeTo, t as byte? ?? 0, bitOffset, isAligned); bitOffset += 8; return; } else if (t is ushort) { value = t as ushort? ?? 0; } else if (t is uint) { value = t as uint? ?? 0; } else { value = t as ulong? ?? 0; } if (value <= 240) { WriteByte(writeTo, (byte)value, bitOffset, isAligned); } else if (value <= 2287) { WriteByte(writeTo, (value - 240) / 256 + 241, bitOffset, isAligned); WriteByte(writeTo, (value - 240) % 256, bitOffset + 8, isAligned); } else if (value <= 67823) { WriteByte(writeTo, 249, bitOffset, isAligned); WriteByte(writeTo, (value - 2288) / 256, bitOffset + 8, isAligned); WriteByte(writeTo, (value - 2288) % 256, bitOffset + 16, isAligned); } else { WriteByte(writeTo, value & 255, bitOffset + 8, isAligned); WriteByte(writeTo, (value >> 8) & 255, bitOffset + 16, isAligned); WriteByte(writeTo, (value >> 16) & 255, bitOffset + 24, isAligned); if (value > 16777215) { WriteByte(writeTo, (value >> 24) & 255, bitOffset + 32, isAligned); if (value > 4294967295) { WriteByte(writeTo, (value >> 32) & 255, bitOffset + 40, isAligned); if (value > 1099511627775) { WriteByte(writeTo, (value >> 40) & 255, bitOffset + 48, isAligned); if (value > 281474976710655) { WriteByte(writeTo, (value >> 48) & 255, bitOffset + 56, isAligned); if (value > 72057594037927935) { WriteByte(writeTo, 255, bitOffset, isAligned); WriteByte(writeTo, (value >> 56) & 255, bitOffset + 64, isAligned); } else { WriteByte(writeTo, 254, bitOffset, isAligned); } } else { WriteByte(writeTo, 253, bitOffset, isAligned); } } else { WriteByte(writeTo, 252, bitOffset, isAligned); } } else { WriteByte(writeTo, 251, bitOffset, isAligned); } } else { WriteByte(writeTo, 250, bitOffset, isAligned); } } bitOffset += BytesToRead(value) * 8; } } }