private static TypeCode GetBestNumberTypeComparison(TypeCode a, TypeCode b) { if (a == b) { return(a); } var ua = a.IsUnsignedNumeric(); var ub = b.IsUnsignedNumeric(); if (ua == ub) { return((TypeCode)Math.Max((int)a, (int)b)); } var unsignedCode = ua ? a : b; var signedCode = ua ? b : a; if (signedCode > unsignedCode) { return(signedCode); } switch (unsignedCode) { case TypeCode.Byte: return(TypeCode.Int16); case TypeCode.UInt16: return(TypeCode.Int32); case TypeCode.UInt32: return(TypeCode.Int64); } return(TypeCode.Double); }
private void WriteNode(BinaryWriter writer, IGraphNode node) { if (node == null) { writer.Write((byte)0); return; } switch (node.DataType) { case SerializedDataType.Boolean: case SerializedDataType.Number: { var n = node as IPrimitiveGraphNode; byte code = 1 << 5; var value = n.Value; TypeCode typeCode = value.GetType().GetTypeCode(); code |= (byte)typeCode; writer.Write(code); switch (typeCode) { case TypeCode.Boolean: writer.Write((bool)value); break; case TypeCode.Char: writer.Write((char)value); break; case TypeCode.SByte: writer.Write((sbyte)value); break; case TypeCode.Byte: writer.Write((byte)value); break; case TypeCode.Int16: writer.Write((short)value); break; case TypeCode.UInt16: writer.Write((ushort)value); break; case TypeCode.Int32: writer.Write((int)value); break; case TypeCode.UInt32: writer.Write((uint)value); break; case TypeCode.Int64: writer.Write((long)value); break; case TypeCode.UInt64: writer.Write((ulong)value); break; case TypeCode.Single: writer.Write((float)value); break; case TypeCode.Double: writer.Write((double)value); break; case TypeCode.Decimal: writer.Write((decimal)value); break; case TypeCode.DateTime: { var d = (DateTime)value; writer.Write(d.ToFileTimeUtc()); } break; default: throw new ArgumentOutOfRangeException("Not supported " + typeCode); } } break; case SerializedDataType.String: { var n = node as IStringGraphNode; byte code = 2 << 5; writer.Write(code); writer.Write(n.Value); } break; case SerializedDataType.DataSequence: { var nodes = node as ISequenceGraphNode; byte code = 3 << 5; writer.Write(code); writer.Write(nodes.Length); foreach (var n in nodes) { WriteNode(writer, n); } } break; case SerializedDataType.Type: { var n = node as ITypeGraphNode; byte code = 4 << 5; writer.Write(code); writer.Write(n.TypeId); } break; case SerializedDataType.Object: { var n = node as IObjectGraphNode; byte code = 5 << 5; if (n.IsReferedMultipleTimes) { code |= 1 << 4; writer.Write(code); writer.Write(n.RefId); } else { writer.Write(code); WriteObjectNode(writer, n); } } break; default: throw new ArgumentOutOfRangeException(); } }
private IGraphNode ReadNode(BinaryReader reader, Graph graph) { byte code = reader.ReadByte(); byte nodeCode = (byte)(code >> 5); byte codeData = (byte)(code & 0x1f); switch (nodeCode) { case 0: return(null); case 1: //SerializedDataType.Boolean or SerializedDataType.Number { TypeCode typeCode = (TypeCode)codeData; ValueType value; switch (typeCode) { case TypeCode.Boolean: value = reader.ReadBoolean(); break; case TypeCode.Char: value = reader.ReadChar(); break; case TypeCode.SByte: value = reader.ReadSByte(); break; case TypeCode.Byte: value = reader.ReadByte(); break; case TypeCode.Int16: value = reader.ReadInt16(); break; case TypeCode.UInt16: value = reader.ReadUInt16(); break; case TypeCode.Int32: value = reader.ReadInt32(); break; case TypeCode.UInt32: value = reader.ReadUInt32(); break; case TypeCode.Int64: value = reader.ReadInt64(); break; case TypeCode.UInt64: value = reader.ReadUInt64(); break; case TypeCode.Single: value = reader.ReadSingle(); break; case TypeCode.Double: value = reader.ReadDouble(); break; case TypeCode.Decimal: value = reader.ReadDecimal(); break; case TypeCode.DateTime: { long time = reader.ReadInt64(); value = DateTime.FromFileTimeUtc(time); } break; default: throw new ArgumentOutOfRangeException("Not supported " + typeCode); } return(graph.BuildPrimitiveNode(value)); } case 2: //SerializedDataType.String return(graph.BuildStringNode(reader.ReadString())); case 3: //SerializedDataType.DataSequence { var n = graph.BuildSequenceNode(); int numOfElements = reader.ReadInt32(); for (int i = 0; i < numOfElements; i++) { var node = ReadNode(reader, graph); n.Add(node); } return(n); } case 4: //SerializedDataType.Type { return(graph.GetTypeEntry(reader.ReadByte())); } case 5: //SerializedDataType.Object { codeData = (byte)(codeData >> 4); if (codeData == 1) { int refId = reader.ReadInt32(); return(graph.GetObjectDataForRefId(refId)); } if (codeData == 0) { return(ReadObjectNode(reader, graph)); } throw new Exception("Invalid bytecode"); } default: throw new ArgumentOutOfRangeException(); } }