diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..866703f --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +################################### +# Git ignore file for Molyjam2012 # +################################### + +#Folders +Library/ +Temp/ +Builds/ +Libraries/ +Debug/ +Release/ +run/ +bin/ +obj/ + +#Project/User Preference Files +*.csproj +*.pidb +*.userprefs +*.user +*.suo + +#OS Junk +Thumbs.db +.DS_Store* +ehthumbs.db +Icon7 + + + +#*.sln diff --git a/Clock.cs b/Clock.cs new file mode 100644 index 0000000..483c567 --- /dev/null +++ b/Clock.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace lib +{ + public class Clock + { + public Clock( long timeOffset ) + { + m_timer = new Timer(); + + m_lastTime = m_timer.Current; + + m_totalMillis = timeOffset; + m_totalSeconds= (double)m_totalMillis / 1000.0; + } + + public void tick() + { + long current = m_timer.Current; + + m_dtMillis = (int)(current - m_lastTime); + + m_dtSeconds = (double)m_dtMillis / 1000.0; + + m_totalMillis += m_dtMillis; + m_totalSeconds = (double)m_totalMillis / 1000.0; + + m_lastTime = current; + } + + public int dtMs { get { return m_dtMillis; } } + public double dtSec { get { return m_dtSeconds; } } + + public long ms { get { return m_totalMillis; } } + public double sec{ get { return m_totalSeconds; } } + + + Timer m_timer; + + long m_lastTime = 0; + + int m_dtMillis = 0; + double m_dtSeconds = 0; + + long m_totalMillis = 0; + double m_totalSeconds = 0; + + } +} diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..38d7181 --- /dev/null +++ b/Config.cs @@ -0,0 +1,158 @@ +using System; +using System.IO; +using System.Xml; +using System.Reflection; + +namespace lib +{ + +[Serializable] +public class ResRefConfig : res.Ref where T: Config +{ + public ResRefConfig() + { + } + + public ResRefConfig( string filename, T cfg ) + : base( filename, cfg ) + { + } + + override public void OnDeserialize( object enclosing ) + { + base.OnDeserialize( enclosing ); + + var cfg = Config.load( filename ); + + res = cfg; + } +} + +[Serializable] +public class Config +{ + /* + static public Config Load( string filename ) + { + return null; + } + */ + + static public void startup() + { + res.Mgr.register( res_load ); + res.Mgr.registerSub( res_load ); + } + + + #region SaveLoad + static public ResRefConfig res_load( string filename ) + { + return new ResRefConfig( filename, load( filename ) ); + } + + static public ResRefConfig res_load( string filename ) where T : Config + { + return new ResRefConfig( filename, load( filename ) ); + } + + /* + static public ResRefConfig res_load( string filename, Type t ) + { + return new ResRefConfig( filename, load( filename, t ) ); + } + */ + + + static public Config load( string filename ) + { + FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read ); + + XmlFormatter2 formatter = new XmlFormatter2(); + + Config cfg = (Config)formatter.Deserialize( fs ); + + return cfg; + } + + static public T load( string filename ) where T : Config + { + return (T)load( filename, typeof( T ) ); + } + + static public Config load( string filename, Type t ) + { + Config cfg = null; + + try + { + FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read ); + + XmlFormatter2 formatter = new XmlFormatter2(); + + cfg = (Config)( t != null ? formatter.DeserializeKnownType( fs,t ) : formatter.Deserialize( fs ) ); + + cfg.SetFilename( filename ); + } + catch( FileNotFoundException ) + { + Type[] types = new Type[ 0 ]; + object[] parms = new object[ 0 ]; + + //types[ 0 ] = typeof( string ); + //parms[ 0 ] = filename; + + ConstructorInfo cons = t.GetConstructor( types ); + + try + { + cfg = (Config)cons.Invoke( parms ); + } + catch( Exception e ) + { + Log.error( "Caught exception {0}", e ); + } + + cfg.SetFilename( filename ); + + Config.save( cfg, filename ); + } + + return cfg; + } + + static public void save( Config cfg ) + { + Config.save( cfg, cfg.m_filename ); + } + + static public void save( Config cfg, String filename ) + { + FileStream fs = new FileStream( filename, FileMode.Create, FileAccess.Write ); + + XmlFormatter2 formatter = new XmlFormatter2(); + + formatter.Serialize( fs, cfg ); + + fs.Close(); + } + #endregion + + private string m_filename = ""; + + public Config() + { + } + + public Config( string filename ) + { + m_filename = filename; + } + + public String Filename { get { return m_filename; } } + + protected void SetFilename( String filename ) { m_filename = filename; } + +} +} + diff --git a/Conn.cs b/Conn.cs new file mode 100644 index 0000000..4b460b5 --- /dev/null +++ b/Conn.cs @@ -0,0 +1,106 @@ +using System; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Net.Sockets; +using System.IO; + +//using Util; + +namespace lib +{ + + + +public class Conn +{ + public Socket Sock { get { return m_socket; } } + public Stream Stream { get { return m_streamNet; } } + public IFormatter Formatter { get { return m_formatter; } } + + + public Conn( Socket sock, IFormatter formatter ) + { + m_socket = sock; + + //sock.DontFragment = true; + sock.NoDelay = true; + + m_streamNet = new NetworkStream( m_socket ); + //m_streamBufIn = new BufferedStream( m_streamNet ); + + m_formatter = formatter; + //m_formatter = new VersionFormatter(); + + //mm_memStream = new MemoryStream( mm_buffer ); + + + } + + public object recieveObject() + { + return recieveObject( Stream ); + } + + public object recieveObject( Stream stream ) + { + object obj = null; + lock( this ) + { + try + { + obj = m_formatter.Deserialize( stream ); + } + catch( System.Xml.XmlException e ) + { + lib.Log.error( "Outer Exception {0}", e.ToString() ); + //lib.Log.error( "Inner Exception {0}", e.InnerException.ToString() ); + } + } + + return obj; + } + + public void send( object obj ) + { + lock( this ) + { + try + { + var ms = new MemoryStream( 1024 ); + m_formatter.Serialize( ms, obj ); + + //var str = System.Text.Encoding.Default.GetString( mm_buffer, 0, (int)ms.Position ); + //lib.Log.info( "Sent data {0} of length {1}", str, ms.Position ); + + byte[] byteSize = BitConverter.GetBytes( (uint)ms.Position ); + m_streamNet.Write( byteSize, 0, 4 ); + m_streamNet.Write( ms.GetBuffer(), 0, (int)ms.Position ); + + m_streamNet.Flush(); + } + catch( Exception e ) + { + //m_streamNet.Close(); + //m_socket.Close(); + } + } + } + + public virtual void recieve( object obj ) + { + //Log.log.msg( "Recieved " + obj.ToString() ); + } + + private Socket m_socket; + + private NetworkStream m_streamNet; + //private BufferedStream m_streamBufIn; + //private BufferedStream m_streamBufOut; + + private IFormatter m_formatter; + +} + + + +} diff --git a/Helpers.cs b/Helpers.cs new file mode 100644 index 0000000..56e08f1 --- /dev/null +++ b/Helpers.cs @@ -0,0 +1,179 @@ + +/* + * TODO: Need to verify types are correct when deserializing. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +using System.Xml; +using System.Xml.Serialization; + +using System.IO; + +namespace lib +{ + public class Helpers + { + public void XmlSave( String filename, Object obj ) + { + FileStream fs = new FileStream( filename, FileMode.Create, FileAccess.Write ); + + XmlSerializer xs = new XmlSerializer( obj.GetType() ); + //MemoryStream memoryStream = new MemoryStream( StringToUTF8ByteArray( pXmlizedString ) ); + //XmlTextReader reader = new XmlTextReader( fs, Encoding.UTF8 ); + + xs.Serialize( fs, obj ); + } + + public Object XmlLoad( String filename ) + { + FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read ); + + XmlSerializer xs = new XmlSerializer( typeof( TType ) ); + //MemoryStream memoryStream = new MemoryStream( StringToUTF8ByteArray( pXmlizedString ) ); + //XmlTextReader reader = new XmlTextReader( fs, Encoding.UTF8 ); + + return xs.Deserialize( fs ); + } + + + static public MethodInfo FindConvertFunction( string typeName ) + { + Type t = typeof( Convert ); + + + MethodInfo[] allMethods = t.GetMethods(); + + foreach( MethodInfo mi in allMethods ) + { + if( mi.GetParameters().Length == 1 ) + { + string paramName = mi.GetParameters()[ 0 ].ParameterType.Name; + + if( paramName == "String" ) + { + if( mi.ReturnType.FullName == typeName ) + { + return mi; + } + } + } + } + + return null; + + } + + static public void SerializeDict( string filename, Dictionary dict ) + { + XmlTextWriter xmlWriter = new XmlTextWriter( filename, null ); + + xmlWriter.Formatting = Formatting.Indented; + + //xmlWriter.WriteStartDocument(); + + xmlWriter.WriteStartElement( "dictionary" ); + + Type[] types = dict.GetType().GetGenericArguments(); + + xmlWriter.WriteAttributeString( "keyType", types[ 0 ].FullName ); + xmlWriter.WriteAttributeString( "valType", types[ 1 ].FullName ); + + foreach( KeyValuePair kvp in dict ) + { + xmlWriter.WriteStartElement( "kvp" ); + + xmlWriter.WriteAttributeString( "key", kvp.Key.ToString() ); + xmlWriter.WriteAttributeString( "value", kvp.Value.ToString() ); + + xmlWriter.WriteEndElement(); + } + + xmlWriter.WriteEndElement(); + + //xmlWriter.WriteEndDocument(); + + xmlWriter.Close(); + } + + static public void DeserializeDict( string filename, Dictionary dict ) + { + FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read ); + + XmlDocument doc = new XmlDocument(); + + doc.Load( fs ); + + //CreateTypeFor() + + XmlElement docElem = doc.DocumentElement; + + if( docElem.Name == "dictionary" ) + { + string keyType = docElem.GetAttribute( "keyType" ); + string valType = docElem.GetAttribute( "valType" ); + + MethodInfo keyMI = FindConvertFunction( keyType ); + MethodInfo valMI = FindConvertFunction( valType ); + + + if( keyMI != null && valMI != null ) + { + XmlNodeList nodeList = docElem.ChildNodes; + + object[] args = new object[ 1 ]; + + //fi.SetValue( newObj, obj ); + + foreach( XmlElement node in nodeList ) + { + if( node.Name == "kvp" ) + { + if( node.Attributes != null ) + { + args[ 0 ] = node.GetAttribute( "key" ); + + TKey key = (TKey)keyMI.Invoke( null, args ); + + args[ 0 ] = node.GetAttribute( "value" ); + + TVal val = (TVal)valMI.Invoke( null, args ); + + dict[ key ] = val; + } + else + { + Log.error( String.Format( "No attributes in node while loading file {0}", filename ) ); + } + } + else + { + Log.error( String.Format( "Incorrect key {0} found while loading file {1}", node.Name, filename ) ); + } + } + } + else + { + if( keyMI == null ) + Log.error( String.Format( "Key type conversion not found for type {0}", keyType ) ); + + if( valMI == null ) + Log.error( String.Format( "Val type conversion not found for type {0}", valType ) ); + } + + } + else + { + Log.error( String.Format( "No dictionary element found while loading file {0}", filename ) ); + } + } + + } + + + +} diff --git a/Log.cs b/Log.cs new file mode 100644 index 0000000..aa05147 --- /dev/null +++ b/Log.cs @@ -0,0 +1,239 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.Collections; +//using System.Threading.Tasks; + +namespace lib +{ + + public delegate void Log_delegate( String type, String cat, String msg ); + + public class Log : TraceListener + { + static public void create( String filename ) + { + s_log = new Log( filename ); + } + + static public void destroy() + { + string msg = "==============================================================================\nLogfile shutdown at " + DateTime.Now.ToString(); + + s_log.writeToAll( "info", "log", msg ); + + s_log.stop(); + + s_log = null; + } + + static private Log s_log; + + static public Log log + { + get + { + return s_log; + } + } + + // Forwards. + static public void error( String msg, params object[] args ) { lock( s_log ) { log.error_i( msg, args ); } } + static public void warn( String msg, params object[] args ) { lock( s_log ) { log.warn_i( msg, args ); } } + static public void info( String msg, params object[] args ) { lock( s_log ) { log.info_i( msg, args ); } } + + + private Log( String filename ) + { + //TODO: Fix this so itll work without a directory. + Directory.CreateDirectory( Path.GetDirectoryName( filename ) ); + + m_stream = new FileStream( filename, FileMode.Append, FileAccess.Write ); + m_writer = new StreamWriter( m_stream ); + + m_errorStream = new FileStream( filename + ".error", FileMode.Append, FileAccess.Write ); + m_errorWriter = new StreamWriter( m_errorStream ); + + Debug.Listeners.Add( this ); + + string msg = "\n==============================================================================\nLogfile " + filename + " startup at " + DateTime.Now.ToString(); + + writeToAll( "info", "log", msg ); + } + + public override void Write( string msg ) + { + WriteLine( msg ); + } + + public override void WriteLine( string msg ) + { + error( msg ); + //base.WriteLine( msg ); + } + + void stop() + { + m_writer.Close(); + m_stream.Close(); + + m_errorWriter.Close(); + m_errorStream.Close(); + } + + public void addDelegate( Log_delegate cb ) + { + m_delegates.Add( cb ); + } + + private void writeFileAndLine( StackTrace st ) + { + StackFrame frame = st.GetFrame( 1 ); + + String srcFile = frame.GetFileName(); + String srcLine = frame.GetFileLineNumber().ToString(); + + Console.WriteLine( "{0} ({1}):", srcFile, srcLine ); + } + + private void writeStack( StackTrace st ) + { + for( int i=0; i { + StackTrace st = new StackTrace( true ); + + writeStack( st ); + + String msgPrint = msg; + + if( args.Length > 0 ) + { + msgPrint = String.Format( msg, args ); + } + + writeToAll( "error", "log", msgPrint ); + //} ); + } + + private void warn_i( String msg, params object[] args ) + { + //var t = Task.Run( () => { + StackTrace st = new StackTrace( true ); + + writeStack( st ); + + String msgPrint = msg; + + if( args.Length > 0 ) + { + msgPrint = String.Format( msg, args ); + } + + writeToAll( "warn", "log", msgPrint ); + //}); + } + + private void info_i( String msg, params object[] args ) + { + //var t = Task.Run( () => { + StackTrace st = new StackTrace( true ); + + String msgPrint = msg; + + if( args.Length > 0 ) + { + msgPrint = String.Format( msg, args ); + } + + writeToAll( "info", "log", msgPrint ); + //} ); + } + + + private Stream m_stream; + private StreamWriter m_writer; + + private Stream m_errorStream; + private StreamWriter m_errorWriter; + + private ArrayList m_delegates = new ArrayList(); + } + + + + + + + + + +} diff --git a/NetMsg.cs b/NetMsg.cs new file mode 100644 index 0000000..582e36e --- /dev/null +++ b/NetMsg.cs @@ -0,0 +1,103 @@ +using System; + +namespace lib.Net +{ + [Serializable] + public class Msg + { + public Msg() + { + } + } + + [Serializable] + public class Login + { + public Login( String name, String pass ) + { + m_username = name; + m_password = pass; + } + + public readonly String m_username; + public readonly String m_password; + } + + [Serializable] + public class LoginResp + { + public LoginResp( bool resp ) + { + m_resp = resp; + } + + public readonly bool m_resp; + } + + #region Admin Messages + //Subclasses of this need to be on an admin client. + [Serializable] + public class Admin + { + + }; + + [Serializable] + public class CreateEntity : Admin + { + + } + + + [Serializable] + public class MoveEntity : Admin + { + + } + #endregion + + [Serializable] + public class EntityBase + { + public EntityBase( int id ) + { + m_id = id; + } + + public readonly int m_id; + }; + + + [Serializable] + public class EntityPos : EntityBase + { + public EntityPos( int id, float x, float y, float z ) : + base( id ) + { + m_x = x; + m_y = y; + m_z = z; + } + + public readonly float m_x; + public readonly float m_y; + public readonly float m_z; + } + + [Serializable] + public class EntityDesc : EntityBase + { + public EntityDesc( int id ) : + base( id ) + { + } + + //Should an entity have a mesh? Be made up of multiple meshes? + public readonly String m_mesh; + } + + + + + +} diff --git a/Pos.cs b/Pos.cs new file mode 100644 index 0000000..5303b84 --- /dev/null +++ b/Pos.cs @@ -0,0 +1,52 @@ +using System; + +namespace lib +{ + +[Serializable] +public struct Pos +{ + public float x { get; private set; } + public float y { get; private set; } + public float z { get; private set; } + + + public Pos( float _x, float _y, float _z ) : this() + { + x = _x; + y = _y; + z = _z; + } + + // overload operator + + public static Pos operator +( Pos a, Pos b ) + { + return new Pos( a.x + b.x, a.y + b.y, a.z + b.z ); + } + + public static Pos operator -( Pos a, Pos b ) + { + return new Pos( a.x - b.x, a.y - b.y, a.z - b.z ); + } + + public static Pos operator /( Pos a, float val ) + { + return new Pos( a.x / val, a.y / val, a.z / val ); + } + + public static Pos operator *( Pos a, float val ) + { + return new Pos( a.x * val, a.y * val, a.z * val ); + } + + public float distSqr( Pos other ) + { + float dx = x - other.x; + float dy = y - other.y; + float dz = z - other.z; + + return dx * dx + dy * dy + dz * dz; + } +} + +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6c7d80d --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Common" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "Allusion Studio, Inc" )] +[assembly: AssemblyProduct( "Common" )] +[assembly: AssemblyCopyright( "Copyright © Allusion Studio, Inc 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "fbc724c2-ea86-47cf-ae0b-f15e11ba6701" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// 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.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/SerializableDictionary.cs b/SerializableDictionary.cs new file mode 100644 index 0000000..1724390 --- /dev/null +++ b/SerializableDictionary.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml.Serialization; +using System.Xml; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; +using System.Security.Permissions; + +namespace lib +{ + [Serializable] + public class SerializableDictionary : Dictionary, IXmlSerializable, ISerializable + { + #region Constants + private const string DictionaryNodeName = "Dictionary"; + private const string ItemNodeName = "Item"; + private const string KeyNodeName = "Key"; + private const string ValueNodeName = "Value"; + #endregion + #region Constructors + public SerializableDictionary() + { + } + + public SerializableDictionary(IDictionary dictionary) + : base(dictionary) + { + } + + public SerializableDictionary(IEqualityComparer comparer) + : base(comparer) + { + } + + public SerializableDictionary(int capacity) + : base(capacity) + { + } + + public SerializableDictionary(IDictionary dictionary, IEqualityComparer comparer) + : base(dictionary, comparer) + { + } + + public SerializableDictionary(int capacity, IEqualityComparer comparer) + : base(capacity, comparer) + { + } + + #endregion + #region ISerializable Members + + protected SerializableDictionary(SerializationInfo info, StreamingContext context) + { + int itemCount = info.GetInt32("ItemCount"); + for (int i = 0; i < itemCount; i++) { + KeyValuePair kvp = (KeyValuePair)info.GetValue(String.Format("Item{0}", i), typeof(KeyValuePair)); + this.Add(kvp.Key, kvp.Value); + } + } + + [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("ItemCount", this.Count); + int itemIdx = 0; + foreach (KeyValuePair kvp in this) { + info.AddValue(String.Format("Item{0}", itemIdx), kvp, typeof(KeyValuePair)); + itemIdx++; + } + } + + #endregion + #region IXmlSerializable Members + + void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) + { + //writer.WriteStartElement(DictionaryNodeName); + foreach (KeyValuePair kvp in this) { + writer.WriteStartElement(ItemNodeName); + writer.WriteStartElement(KeyNodeName); + KeySerializer.Serialize(writer, kvp.Key); + writer.WriteEndElement(); + writer.WriteStartElement(ValueNodeName); + ValueSerializer.Serialize(writer, kvp.Value); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + //writer.WriteEndElement(); + } + + void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) + { + if (reader.IsEmptyElement) { + return; + } + + // Move past container + if (!reader.Read()){ + throw new XmlException("Error in Deserialization of Dictionary"); + } + + //reader.ReadStartElement(DictionaryNodeName); + while (reader.NodeType != XmlNodeType.EndElement) { + reader.ReadStartElement(ItemNodeName); + reader.ReadStartElement(KeyNodeName); + TKey key = (TKey)KeySerializer.Deserialize(reader); + reader.ReadEndElement(); + reader.ReadStartElement(ValueNodeName); + TVal value = (TVal)ValueSerializer.Deserialize(reader); + reader.ReadEndElement(); + reader.ReadEndElement(); + this.Add(key, value); + reader.MoveToContent(); + } + //reader.ReadEndElement(); + + reader.ReadEndElement(); // Read End Element to close Read of containing node + } + + System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() + { + return null; + } + + #endregion + #region Private Properties + protected XmlSerializer ValueSerializer + { + get + { + if (valueSerializer == null) { + valueSerializer = new XmlSerializer(typeof(TVal)); + } + return valueSerializer; + } + } + + private XmlSerializer KeySerializer + { + get + { + if (keySerializer == null) { + keySerializer = new XmlSerializer(typeof(TKey)); + } + return keySerializer; + } + } + #endregion + #region Private Members + private XmlSerializer keySerializer = null; + private XmlSerializer valueSerializer = null; + #endregion + } +} diff --git a/SharpLib.sln b/SharpLib.sln new file mode 100644 index 0000000..49408e4 --- /dev/null +++ b/SharpLib.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpLib", "SharpLib.csproj", "{DED134FC-C282-49C9-BA02-3CE6257E91FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DED134FC-C282-49C9-BA02-3CE6257E91FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DED134FC-C282-49C9-BA02-3CE6257E91FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DED134FC-C282-49C9-BA02-3CE6257E91FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DED134FC-C282-49C9-BA02-3CE6257E91FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Timer.cs b/Timer.cs new file mode 100644 index 0000000..b60287f --- /dev/null +++ b/Timer.cs @@ -0,0 +1,95 @@ +using System; +using System.Runtime.InteropServices; +using System.ComponentModel; +using System.Threading; + +namespace lib +{ + public class Timer + { + [DllImport("Kernel32.dll")] + private static extern bool QueryPerformanceCounter( + out long lpPerformanceCount); + + [DllImport("Kernel32.dll")] + private static extern bool QueryPerformanceFrequency( + out long lpFrequency); + + private long startTime; + private long stopTime; + private long freq; + private long freq_millis; + + // Constructor + + public Timer() + { + startTime = 0; + stopTime = 0; + + if (QueryPerformanceFrequency(out freq) == false) + { + // high-performance counter not supported + throw new Win32Exception(); + } + + freq_millis = freq / 1000; + + } + + // Start the timer + + public void Start() + { + // lets do the waiting threads there work + + //Thread.Sleep(0); + + QueryPerformanceCounter(out startTime); + } + + // Stop the timer + + public void Stop() + { + QueryPerformanceCounter(out stopTime); + } + + public double Seconds + { + get + { + long current; + + QueryPerformanceCounter( out current ); + + return (double)( current - startTime ) / freq; + } + } + + public long Current + { + get + { + long current; + + QueryPerformanceCounter( out current ); + + return ( current - startTime ) / freq_millis; + } + } + + public double Duration + { + get + { + return (double)( stopTime - startTime ) / (double)freq; + } + } + + public long DurationMS + { + get { return (stopTime - startTime) / freq_millis; } + } + } +} diff --git a/Token.cs b/Token.cs new file mode 100644 index 0000000..4bbe8a5 --- /dev/null +++ b/Token.cs @@ -0,0 +1,46 @@ +using System; +using System.Diagnostics; + +namespace lib +{ +[Serializable] +public struct Token +{ + public string str { get{ return m_str; } } + + public Token( String str ) + { + m_str = str; + m_hash = m_str.GetHashCode(); + } + + public override bool Equals( object obj ) + { + if( !( obj is Token ) ) + return false; + + //This doesnt use as because Token is a struct + var otherId = (Token)obj; + + if( m_hash != otherId.m_hash ) + return false; + + return m_str == otherId.m_str; + } + + + public bool Equals_fast( Token other ) + { + return m_hash == other.m_hash && m_str == other.m_str; + } + + public override int GetHashCode() + { + return m_hash; + } + + int m_hash; + String m_str; +} + +} diff --git a/UpgradeLog.XML b/UpgradeLog.XML new file mode 100644 index 0000000..70a8c8b Binary files /dev/null and b/UpgradeLog.XML differ diff --git a/UpgradeLog.htm b/UpgradeLog.htm new file mode 100644 index 0000000..0cbd10f Binary files /dev/null and b/UpgradeLog.htm differ diff --git a/VersionFormatter.cs b/VersionFormatter.cs new file mode 100644 index 0000000..72159df --- /dev/null +++ b/VersionFormatter.cs @@ -0,0 +1,670 @@ +using System; +using System.IO; +using System.Reflection; +using System.Collections; +using System.Diagnostics; +//using System.Globalization; +//using System.ComponentModel; +using System.Runtime.Serialization; + +namespace lib +{ + /// + /// + /// + public class VersionFormatter : IFormatter + { + public enum ETypes + { + Array, + Int32, + Ref, + Object, + EndObject, + Single, + Double, + Char, + String, + Boolean, + EndStream, + } + + + public VersionFormatter() + { + // + // TODO: Add constructor logic here + // + } + + + #region Useless + public ISurrogateSelector SurrogateSelector + { + get + { + return null; + } + + set + { + } + } + + public SerializationBinder Binder + { + get + { + return null; + } + + set + { + } + } + + public StreamingContext Context + { + get + { + return new StreamingContext(); + } + + set + { + } + } + #endregion Useless + + Queue m_objectsToBeDeserialized = new Queue(); + Hashtable m_alreadyDeserialzied = new Hashtable(); + //int m_GUID = 0; + + #region Serialize + public void Serialize( Stream stream, object obj ) + { + //Default is 4k + //BufferedStream bufStream = new BufferedStream( stream ); + + BinaryWriter writer = new BinaryWriter( stream ); + + writeObject( writer, obj ); + + while( m_objectsToBeDeserialized.Count != 0 ) + { + object objToDes = m_objectsToBeDeserialized.Dequeue(); + + writeObject( writer, objToDes ); + } + + writer.Write( (char)ETypes.EndStream ); + } + + void writeRefAndSched( BinaryWriter writer, object obj ) + { + //if( m_alreadyDeserialzied[ obj.GetType().GetArrayRank( + + if( obj == null ) + { + writer.Write( 0 ); + return; + } + + + //Now write the address. + //Bad bad. Need to do this correctly. + int objRef = obj.GetHashCode(); + writer.Write( objRef ); + + if( m_alreadyDeserialzied[ obj ] == null ) + { + m_alreadyDeserialzied[ obj ] = obj; + m_objectsToBeDeserialized.Enqueue( obj ); + } + } + + void dispatchWrite( BinaryWriter writer, object parentObj, FieldInfo fi ) + { + string typeName = fi.FieldType.Name; + + string name = fi.Name; + + if( fi.IsNotSerialized ) + { + return; + } + + if( fi.FieldType.IsArray ) + { + writer.Write( (char)ETypes.Array ); + writer.Write( name.GetHashCode() ); + + writeArray( writer, (Array)fi.GetValue( parentObj ) ); + } + else if( ( fi.FieldType.IsClass || fi.FieldType.IsInterface ) && typeName != "String" ) + { + writer.Write( (char)ETypes.Ref ); + writer.Write( name.GetHashCode() ); + + writeRefAndSched( writer, fi.GetValue( parentObj ) ); + } + else if( fi.FieldType.IsEnum ) + { + writer.Write( (char)ETypes.Int32 ); + writer.Write( name.GetHashCode() ); + + write( writer, Convert.ToInt32( fi.GetValue( parentObj ) ) ); + } + else + { + switch( typeName ) + { + case "Int32": + writer.Write( (char)ETypes.Int32 ); + writer.Write( name.GetHashCode() ); + + write( writer, Convert.ToInt32( fi.GetValue( parentObj ) ) ); + break; + case "Single": + writer.Write( (char)ETypes.Single ); + writer.Write( name.GetHashCode() ); + + write( writer, Convert.ToSingle( fi.GetValue( parentObj ) ) ); + break; + case "Double": + writer.Write( (char)ETypes.Double ); + writer.Write( name.GetHashCode() ); + + write( writer, Convert.ToDouble( fi.GetValue( parentObj ) ) ); + break; + case "Char": + writer.Write( (char)ETypes.Char ); + writer.Write( name.GetHashCode() ); + + write( writer, Convert.ToChar( fi.GetValue( parentObj ) ) ); + break; + case "String": + writer.Write( (char)ETypes.String ); + writer.Write( name.GetHashCode() ); + + write( writer, Convert.ToString( fi.GetValue( parentObj ) ) ); + break; + case "Boolean": + writer.Write( (char)ETypes.Boolean ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToBoolean( fi.GetValue( parentObj ) ) ); + break; + default: + Console.WriteLine( "VersionFormatter does not understand type " + typeName ); + break; + } + } + } + + void writeArray( BinaryWriter writer, Array array ) + { + if( array == null ) + { + writer.Write( (int)-1 ); + return; + } + + writer.Write( array.Length ); + + foreach( object obj in array ) + { + writeRefAndSched( writer, obj ); + } + } + + void getAllFields( object obj, ArrayList list ) + { + Type t = obj.GetType(); + + while( t != null ) + { + FieldInfo[] fiArr = t.GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly ); + list.AddRange( fiArr ); + + t = t.BaseType; + } + } + + + void writeObject( BinaryWriter writer, object obj ) + { + Type objType = obj.GetType(); + + writer.Write( (char)ETypes.Object ); + writer.Write( objType.FullName ); + + int objRef = obj.GetHashCode(); + writer.Write( objRef ); + + ArrayList list = new ArrayList(); + + getAllFields( obj, list ); + + foreach( FieldInfo fi in list ) + { + dispatchWrite( writer, obj, fi ); + } + + writer.Write( (char)ETypes.EndObject ); + } + + void write( BinaryWriter wr, TType val ) + { + //wr.Write( val ); + } + + /* + void writeInt( BinaryWriter writer, int val ) + { + writer.Write( val ); + } + + void writeSingle( BinaryWriter writer, float val ) + { + writer.Write( val ); + } + + void writeDouble( BinaryWriter writer, double val ) + { + writer.Write( val ); + } + + void writeChar( BinaryWriter writer, char val ) + { + writer.Write( val ); + } + + void writeString( BinaryWriter writer, string val ) + { + writer.Write( val ); + } + + void writeBool( BinaryWriter writer, bool val ) + { + writer.Write( val ); + } + */ + #endregion Serialize + + + #region Deserialize + + class Fixup + { + public Fixup( int guid, object obj, FieldInfo fi ) + { + m_guid= guid; + m_obj = obj; + m_fi = fi; + } + + public Fixup( int guid, object obj, int index ) + { + m_guid = guid; + m_obj = obj; + m_index= index; + } + + public readonly int m_guid = 0; + public readonly object m_obj = null; + + public readonly FieldInfo m_fi = null; + public readonly int m_index= -1; + + } + + Hashtable m_mapGUIDToObject = new Hashtable(); + ArrayList m_fixupList = new ArrayList(); + + ArrayList m_desObjects = new ArrayList(); + + public object Deserialize( Stream stream ) + { + BinaryReader reader = new BinaryReader( stream ); + + object objRoot = null; + + //Read in the first object. + { + ETypes type = (ETypes)reader.ReadChar(); + + Debug.Assert( type == ETypes.Object ); + + objRoot = readObject( reader ); + + m_desObjects.Add( objRoot ); + } + + bool readObjects = true; + + while( readObjects ) + { + ETypes type = (ETypes)reader.ReadChar(); + + Debug.Assert( type == ETypes.Object || type == ETypes.EndStream ); + + if( type == ETypes.Object ) + { + object obj = readObject( reader ); + + m_desObjects.Add( obj ); + } + else + { + Debug.Assert( type == ETypes.EndStream ); + + readObjects = false; + } + } + + foreach( Fixup fu in m_fixupList ) + { + //Fixup fix = m_fixups[ + + object obj = m_mapGUIDToObject[ fu.m_guid ]; + + if( obj != null ) + { + if( fu.m_fi != null ) + { + fu.m_fi.SetValue( fu.m_obj, obj ); + } + else + { + Debug.Assert( fu.m_index >= 0 ); + + object []array = (object [])fu.m_obj; + + array[ fu.m_index ] = obj; + } + } + else + { + Console.WriteLine( "Obj to ref is null." ); + } + } + + foreach( object obj in m_desObjects ) + { + if( typeof( IDeserializationCallback ).IsAssignableFrom( obj.GetType() ) ) + { + IDeserializationCallback desCB = (IDeserializationCallback)obj; + + if( desCB != null ) + { + desCB.OnDeserialization( this ); + } + } + } + + return objRoot; + } + + + + bool dispatchRead( BinaryReader reader, object obj, Hashtable ht ) + { + + //Read the type + ETypes type = (ETypes)reader.ReadChar(); + + if( type == ETypes.EndObject ) + { + return false; + } + + int nameHash = reader.ReadInt32(); + + FieldInfo fi = (FieldInfo)ht[ nameHash ]; + + if( fi == null ) + { + Console.WriteLine( "Field no longer exists" ); + } + + try + { + switch( type ) + { + case ETypes.Array: + readArray( reader, obj, fi ); + break; + case ETypes.Int32: + readInt( reader, obj, fi ); + break; + case ETypes.Single: + readSingle( reader, obj, fi ); + break; + case ETypes.Double: + readDouble( reader, obj, fi ); + break; + case ETypes.Char: + readChar( reader, obj, fi ); + break; + case ETypes.Boolean: + readBool( reader, obj, fi ); + break; + case ETypes.String: + readString( reader, obj, fi ); + break; + case ETypes.Ref: + readRef( reader, obj, fi ); + break; + case ETypes.Object: + readObject( reader ); + break; + default: + Debug.Fail( "Unknown type on read." ); + break; + } + } + catch( Exception ex ) + { + Console.WriteLine( "Exception: " + ex.Message ); + Console.WriteLine( "Stack: " + ex.StackTrace ); + } + + + return true; + } + + object createObject( string objTypeName ) + { + Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); + + foreach( Assembly a in ass ) + { + Type t = a.GetType( objTypeName ); + + if( t != null ) + { + object obj = FormatterServices.GetUninitializedObject( t ); + + if( obj != null ) + { + return obj; + } + } + } + + return null; + } + + + object readObject( BinaryReader reader ) + { + //ETypes type = (ETypes)reader.ReadChar(); + + //Debug.Assert( type == ETypes.Object, "Expecting type Object" ); + + string objTypeName = reader.ReadString(); + int objGUID = reader.ReadInt32(); + + try + { + object obj = createObject( objTypeName ); + + m_mapGUIDToObject[ objGUID ] = obj; + + ArrayList list = new ArrayList(); + Hashtable ht = new Hashtable(); + + if( obj != null ) + { + getAllFields( obj, list ); + + foreach( FieldInfo fi in list ) + { + ht[ fi.Name.GetHashCode() ] = fi; + } + } + + while( dispatchRead( reader, obj, ht ) ) + { + } + + return obj; + } + catch( Exception ex ) + { + Console.WriteLine( "Exception: " + ex.Message ); + } + + return null; + } + + void readArray( BinaryReader reader, object obj, FieldInfo fi ) + { + int length = reader.ReadInt32(); + + if( length < 0 ) + { + if( fi == null ) return; + + fi.SetValue( obj, null ); + + return; + } + + object[] array = new object[length]; + + if( fi != null ) + { + fi.SetValue( obj, array ); + } + + for( int i=0; i m_alreadySerialized = new Dictionary(); + + public object Deserialize( XmlElement elem ) + { + string strType = elem.GetAttribute( "t" ); + + return Deserialize( elem, strType ); + } + + public object Deserialize( XmlElement elem, string strType ) + { + Type type = Type.GetType( strType ); + + MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type ); + + object obj = Activator.CreateInstance( type ); + + + /* + object obj = FormatterServices.GetUninitializedObject( type ); + + + ConstructorInfo[] ciArr = obj.GetType().GetConstructors(); + + ConstructorInfo ci = getNoParamCons( ciArr ); + + if( ci == null ) + return null; + + obj = ci.Invoke( null ); + */ + + for( int i = 0; i < miArr.Length; ++i ) + { + FieldInfo fi = (FieldInfo)miArr[ i ]; + + XmlNodeList nodeList = elem.GetElementsByTagName( fi.Name ); + + if( nodeList.Count == 1 ) + { + Type t = fi.FieldType; + + TypeCode tc = Type.GetTypeCode( t ); + + XmlElement child = (XmlElement)nodeList[ 0 ]; + + object childObj = null; + + if( tc != TypeCode.Object || fi.FieldType.FullName == "System.String" ) + { + childObj = s_conv.Convert( child.GetAttribute( "v" ), fi.FieldType ); + } + else + { + if( !t.IsArray ) + { + string refStr = child.GetAttribute( "ref" ); + int refInt = Convert.ToInt32( refStr ); + + if( child.HasAttribute( "t" ) ) + { + childObj = Deserialize( child ); + + m_alreadySerialized[ refInt ] = childObj; + } + else + { + childObj = m_alreadySerialized[ refInt ]; + } + } + else + { + //FormatterServices.GetUninitializedObject() + + int length = s_conv.ToInt32( child.GetAttribute( "c" ) ); + + string elemType = child.GetAttribute( "t" ); + + Array arr = Array.CreateInstance( t.GetElementType(), length ); + + XmlNodeList arrNodeList = child.ChildNodes; + + for( int iElems = 0; iElems < arr.Length; ++iElems ) + { + XmlElement arrElem = (XmlElement)arrNodeList.Item( iElems ); + + arr.SetValue( Deserialize( arrElem, elemType ), iElems ); + } + } + } + + fi.SetValue( obj, childObj ); + } + else + { + if( nodeList.Count == 0 ) + { + // Should be + + //object obj2 = fi.GetRawConstantValue(); + } + else //More than 1. + { + //Log.error( "Too many fields named the same thing" ); + } + } + } + + //FieldInfo fi = (FieldInfo)miArr[0]; + + //ConstructorInfo ci = fi.FieldType.TypeInitializer; + + //ci.Invoke( null ); + + return obj; + } + + + /* + public T Deserialize (Stream stream) + { + return (T) Deserialize (XmlReader.Create (stream), typeof (T)); + } + + public T Deserialize (XmlReader reader) + { + return (T) Deserialize (reader, typeof (T), false); + } + + public T Deserialize (XmlReader reader, bool readContentOnly) + { + return (T) Deserialize (reader, typeof (T), readContentOnly); + } + */ + + public void Serialize( Stream stream, object graph ) + { + /* + XmlWriterSettings settings = new XmlWriterSettings(); + + settings.Indent = true; + + Serialize( XmlWriter.Create( stream, settings ), graph ); + */ + + XmlTextWriter writer = new XmlTextWriter( stream, null ); + + writer.Formatting = Formatting.Indented; + + Serialize( writer, graph ); + + writer.Close(); + } + + public void Serialize (XmlWriter writer, object graph) + { + Serialize (writer, graph, null, true, false, true); + } + + public void Serialize (XmlWriter writer, object graph, + Type rootType, bool preserveObjectReferences, + bool writeContentOnly, + bool ignoreUnknownSerializationData) + { + Type t = graph.GetType(); + + //writer.WriteStartDocument(); + + if( Type.GetTypeCode( t ) == TypeCode.Object ) + { + writer.WriteStartElement( "root" ); + + Assembly assem = t.Assembly; + + string assemName = assem.GetName().Name; + + writer.WriteAttributeString( "t", graph.GetType().FullName + ", " + assemName ); + + FieldInfo[] fiArr = t.GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly ); + + foreach( FieldInfo fi in fiArr ) + { + Serialize( writer, fi.Name, fi.GetValue( graph ) ); + + /* + if( fi.FieldType.IsClass ) + { + Serialize( writer, fi.GetValue( graph ), rootType, preserveObjectReferences, writeContentOnly, ignoreUnknownSerializationData ); + } + else + { + SerializePod( writer, fi.GetValue( graph ) ); + } + */ + } + + writer.WriteEndElement(); + } + + //writer.WriteEndDocument(); + } + + private ObjectIDGenerator m_idGenerator = new ObjectIDGenerator(); + private Dictionary m_alreadyDeserialzied = new Dictionary(); + + public void Serialize( XmlWriter writer, string name, object obj ) + { + writer.WriteStartElement( name ); + + if( obj != null ) + { + Type t = obj.GetType(); + + if( Type.GetTypeCode( t ) == TypeCode.Object ) + { + bool first = false; + if( !m_alreadyDeserialzied.ContainsKey( m_idGenerator.GetId( obj, out first ) ) ) + { + m_alreadyDeserialzied[ m_idGenerator.GetId( obj, out first ) ] = obj; + + Assembly assem = t.Assembly; + + string assemName = assem.GetName().Name; + + if( !t.IsArray ) + { + writer.WriteAttributeString( "t", t.FullName + ", " + assemName ); + + writer.WriteAttributeString( "ref", m_idGenerator.GetId( obj, out first ).ToString() ); + + FieldInfo[] fiArr = t.GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public ); + + foreach( FieldInfo fi in fiArr ) + { + Serialize( writer, fi.Name, fi.GetValue( obj ) ); + } + } + else + { + Array arr = (Array)obj; + + Type aType = t.GetElementType(); + + string aTypeString = aType.FullName; + + writer.WriteAttributeString( "t", aTypeString + ", " + assemName ); + + writer.WriteAttributeString( "c", arr.Length.ToString() ); + + for( int i = 0; i < arr.Length; ++i ) + { + Serialize( writer, "val", arr.GetValue(i) ); + } + + //writer.WriteStartElement( "values" ); + + + + //writer.WriteEndElement(); + + } + } + else + { + writer.WriteAttributeString( "ref", m_idGenerator.GetId( obj, out first ).ToString() ); + } + } + else + { + writer.WriteAttributeString( "t", t.FullName ); + + writer.WriteAttributeString( "v", obj.ToString() ); + } + } + else + { + writer.WriteAttributeString( "null", "" ); + } + + writer.WriteEndElement(); + } + + } +} + + + + + + + + + + + + + + + + + + + /* + /// + /// + /// + public class XmlFormatter : IFormatter + { + public enum ETypes + { + Array, + Int32, + Ref, + Object, + EndObject, + Single, + Double, + Char, + String, + Boolean, + EndStream, + } + + + public XmlFormatter() + { + // + // TODO: Add constructor logic here + // + } + + + #region Useless + public ISurrogateSelector SurrogateSelector + { + get + { + return null; + } + + set + { + } + } + + public SerializationBinder Binder + { + get + { + return null; + } + + set + { + } + } + + public StreamingContext Context + { + get + { + return new StreamingContext(); + } + + set + { + } + } + #endregion Useless + + Queue m_objectsToBeDeserialized = new Queue(); + Hashtable m_alreadyDeserialzied = new Hashtable(); + //int m_GUID = 0; + + #region Serialize + public void Serialize( System.IO.Stream stream, object obj ) + { + //Default is 4k + //BufferedStream bufStream = new BufferedStream( stream ); + + TextWriter writer = new StreamWriter( stream ); + + writeObject( writer, obj ); + + while( m_objectsToBeDeserialized.Count != 0 ) + { + object objToDes = m_objectsToBeDeserialized.Dequeue(); + + writeObject( writer, objToDes ); + } + + writer.Write( (char)ETypes.EndStream ); + } + + void writeRefAndSched( TextWriter writer, object obj ) + { + //if( m_alreadyDeserialzied[ obj.GetType().GetArrayRank( + + if( obj == null ) + { + writer.Write( 0 ); + return; + } + + + //Now write the address. + //Bad bad. Need to do this correctly. + int objRef = obj.GetHashCode(); + writer.Write( objRef ); + + if( m_alreadyDeserialzied[ obj ] == null ) + { + m_alreadyDeserialzied[ obj ] = obj; + m_objectsToBeDeserialized.Enqueue( obj ); + } + } + + void dispatchWrite( TextWriter writer, object parentObj, FieldInfo fi ) + { + string typeName = fi.FieldType.Name; + + string name = fi.Name; + + if( fi.IsNotSerialized ) + { + return; + } + + if( fi.FieldType.IsArray ) + { + writer.Write( (char)ETypes.Array ); + writer.Write( name.GetHashCode() ); + + writeArray( writer, (Array)fi.GetValue( parentObj ) ); + } + else if( ( fi.FieldType.IsClass || fi.FieldType.IsInterface ) && typeName != "String" ) + { + writer.Write( (char)ETypes.Ref ); + writer.Write( name.GetHashCode() ); + + writeRefAndSched( writer, fi.GetValue( parentObj ) ); + } + else if( fi.FieldType.IsEnum ) + { + writer.Write( (char)ETypes.Int32 ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToInt32( fi.GetValue( parentObj ) ) ); + } + else + { + switch( typeName ) + { + case "Int32": + writer.Write( (char)ETypes.Int32 ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToInt32( fi.GetValue( parentObj ) ) ); + break; + case "Single": + writer.Write( (char)ETypes.Single ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToSingle( fi.GetValue( parentObj ) ) ); + break; + case "Double": + writer.Write( (char)ETypes.Double ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToDouble( fi.GetValue( parentObj ) ) ); + break; + case "Char": + writer.Write( (char)ETypes.Char ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToChar( fi.GetValue( parentObj ) ) ); + break; + case "String": + writer.Write( (char)ETypes.String ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToString( fi.GetValue( parentObj ) ) ); + break; + case "Boolean": + writer.Write( (char)ETypes.Boolean ); + writer.Write( name.GetHashCode() ); + + writer.Write( Convert.ToBoolean( fi.GetValue( parentObj ) ) ); + break; + default: + Console.WriteLine( "VersionFormatter does not understand type " + typeName ); + break; + } + } + } + + void writeArray( TextWriter writer, Array array ) + { + if( array == null ) + { + writer.Write( (int)-1 ); + return; + } + + writer.Write( array.Length ); + + foreach( object obj in array ) + { + writeRefAndSched( writer, obj ); + } + } + + void getAllFields( object obj, ArrayList list ) + { + Type t = obj.GetType(); + + while( t != null ) + { + FieldInfo[] fiArr = t.GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly ); + list.AddRange( fiArr ); + + t = t.BaseType; + } + } + + + void writeObject( TextWriter writer, object obj ) + { + Type objType = obj.GetType(); + + writer.Write( (char)ETypes.Object ); + writer.Write( objType.FullName ); + + int objRef = obj.GetHashCode(); + writer.Write( objRef ); + + ArrayList list = new ArrayList(); + + getAllFields( obj, list ); + + foreach( FieldInfo fi in list ) + { + dispatchWrite( writer, obj, fi ); + } + + writer.Write( (char)ETypes.EndObject ); + } + + void write( TextWriter wr, TType val ) + { + //wr.Write( val ); + } + + /* + void writeInt( TextWriter writer, int val ) + { + writer.Write( val ); + } + + void writeSingle( TextWriter writer, float val ) + { + writer.Write( val ); + } + + void writeDouble( TextWriter writer, double val ) + { + writer.Write( val ); + } + + void writeChar( TextWriter writer, char val ) + { + writer.Write( val ); + } + + void writeString( TextWriter writer, string val ) + { + writer.Write( val ); + } + + void writeBool( TextWriter writer, bool val ) + { + writer.Write( val ); + } + * / + #endregion Serialize + + + #region Deserialize + + class Fixup + { + public Fixup( int guid, object obj, FieldInfo fi ) + { + m_guid= guid; + m_obj = obj; + m_fi = fi; + } + + XmlFormatter + + public Fixup( int guid, object obj, int index ) + { + m_guid = guid; + m_obj = obj; + m_index= index; + } + + public readonly int m_guid = 0; + public readonly object m_obj = null; + + public readonly FieldInfo m_fi = null; + public readonly int m_index= -1; + + } + + Hashtable m_mapGUIDToObject = new Hashtable(); + ArrayList m_fixupList = new ArrayList(); + + ArrayList m_desObjects = new ArrayList(); + + public object Deserialize( System.IO.Stream stream ) + { + StreamReader reader = new StreamReader( stream ); + + object objRoot = null; + + //Read in the first object. + { + ETypes type = (ETypes)reader.ReadChar(); + + Debug.Assert( type == ETypes.Object ); + + objRoot = readObject( reader ); + + m_desObjects.Add( objRoot ); + } + + bool readObjects = true; + + while( readObjects ) + { + ETypes type = (ETypes)reader.ReadChar(); + + Debug.Assert( type == ETypes.Object || type == ETypes.EndStream ); + + if( type == ETypes.Object ) + { + object obj = readObject( reader ); + + m_desObjects.Add( obj ); + } + else + { + Debug.Assert( type == ETypes.EndStream ); + + readObjects = false; + } + } + + foreach( Fixup fu in m_fixupList ) + { + //Fixup fix = m_fixups[ + + object obj = m_mapGUIDToObject[ fu.m_guid ]; + + if( obj != null ) + { + if( fu.m_fi != null ) + { + fu.m_fi.SetValue( fu.m_obj, obj ); + } + else + { + Debug.Assert( fu.m_index >= 0 ); + + object []array = (object [])fu.m_obj; + + array[ fu.m_index ] = obj; + } + } + else + { + Console.WriteLine( "Obj to ref is null." ); + } + } + + foreach( object obj in m_desObjects ) + { + if( typeof( IDeserializationCallback ).IsAssignableFrom( obj.GetType() ) ) + { + IDeserializationCallback desCB = (IDeserializationCallback)obj; + + if( desCB != null ) + { + desCB.OnDeserialization( this ); + } + } + } + + return objRoot; + } + + + + bool dispatchRead( StreamReader reader, object obj, Hashtable ht ) + { + + //Read the type + ETypes type = (ETypes)reader.ReadChar(); + + if( type == ETypes.EndObject ) + { + return false; + } + + int nameHash = reader.ReadInt32(); + + FieldInfo fi = (FieldInfo)ht[ nameHash ]; + + if( fi == null ) + { + Console.WriteLine( "Field no longer exists" ); + } + + try + { + switch( type ) + { + case ETypes.Array: + readArray( reader, obj, fi ); + break; + case ETypes.Int32: + readInt( reader, obj, fi ); + break; + case ETypes.Single: + readSingle( reader, obj, fi ); + break; + case ETypes.Double: + readDouble( reader, obj, fi ); + break; + case ETypes.Char: + readChar( reader, obj, fi ); + break; + case ETypes.Boolean: + readBool( reader, obj, fi ); + break; + case ETypes.String: + readString( reader, obj, fi ); + break; + case ETypes.Ref: + readRef( reader, obj, fi ); + break; + case ETypes.Object: + readObject( reader ); + break; + default: + Debug.Fail( "Unknown type on read." ); + break; + } + } + catch( Exception ex ) + { + Console.WriteLine( "Exception: " + ex.Message ); + Console.WriteLine( "Stack: " + ex.StackTrace ); + } + + + return true; + } + + object createObject( string objTypeName ) + { + Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); + + foreach( Assembly a in ass ) + { + Type t = a.GetType( objTypeName ); + + if( t != null ) + { + object obj = FormatterServices.GetUninitializedObject( t ); + + if( obj != null ) + { + return obj; + } + } + } + + return null; + } + + + object readObject( StreamReader reader ) + { + //ETypes type = (ETypes)reader.ReadChar(); + + //Debug.Assert( type == ETypes.Object, "Expecting type Object" ); + + string objTypeName = reader.ReadString(); + int objGUID = reader.ReadInt32(); + + try + { + object obj = createObject( objTypeName ); + + m_mapGUIDToObject[ objGUID ] = obj; + + ArrayList list = new ArrayList(); + Hashtable ht = new Hashtable(); + + if( obj != null ) + { + getAllFields( obj, list ); + + foreach( FieldInfo fi in list ) + { + ht[ fi.Name.GetHashCode() ] = fi; + } + } + + while( dispatchRead( reader, obj, ht ) ) + { + } + + return obj; + } + catch( Exception ex ) + { + Console.WriteLine( "Exception: " + ex.Message ); + } + + return null; + } + + void readArray( StreamReader reader, object obj, FieldInfo fi ) + { + int length = reader.ReadInt32(); + + if( length < 0 ) + { + if( fi == null ) return; + + fi.SetValue( obj, null ); + + return; + } + + object[] array = new object[length]; + + if( fi != null ) + { + fi.SetValue( obj, array ); + } + + for( int i=0; i() + { + return default( T ); + } + + private object DeserializeConcrete( XmlElement elem, Type type ) + { + string val = elem.GetAttribute( "v" ); + + if( !type.IsEnum ) + { + try + { + return s_conv.Convert( val, type ); + } + catch( Exception e ) + { + return GetDefault( type ); + } + } + else + { + return Enum.Parse( type, val ); + } + + } + + private XmlElement getNamedChild( XmlNodeList list, string name ) + { + foreach( XmlNode node in list ) + { + if( node.Name == name ) + { + return (XmlElement)node; + } + } + + return null; + } + + private Type FindType( string shortname ) + { + Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); + + foreach( Assembly a in ass ) + { + Type t = a.GetType( shortname ); + + if( t != null ) + { + return t; + } + } + + return null; + } + + private object DeserializeObject( XmlElement elem, Type type ) + { + string refString = elem.GetAttribute( "ref" ); + + int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1; + + var finalType = type; + if( elem.HasAttribute( "t" ) ) + { + var typename = elem.GetAttribute( "t" ); + finalType = FindType( typename ); + + if( finalType == null ) finalType = type; + } + + object obj = createObject( finalType, refInt ); + + if( obj is IList ) + { + var list = obj as IList; + + return DeserializeList( elem, type, list ); + } + + Type typeISerializable = typeof( ISerializable ); + + //* + /* + if( obj is ISerializable ) // type.IsSubclassOf( typeISerializable ) ) + { + XmlNodeList allChildren = elem.ChildNodes; + + ISerializable ser = obj as ISerializable; + + var serInfo = new SerializationInfo( type, new FormatterConverter() ); + + ser.GetObjectData( serInfo, Context ); + + //var serEnum = ; + + foreach( var serMember in serInfo ) + { + String name = serMember.Name; + + name = name.Replace( '+', '-' ); + name = name.Replace( '`', '_' ); + + XmlElement childElem = getNamedChild( allChildren, name ); + + var des = Deserialize( childElem, name ); + } + } + else + */ + { + MemberInfo[] miArr = FormatterServices.GetSerializableMembers( finalType ); + + XmlNodeList allChildren = elem.ChildNodes; + + for( int i = 0; i < miArr.Length; ++i ) + { + FieldInfo childFi = (FieldInfo)miArr[ i ]; + + String name = childFi.Name; + + name = name.Replace( '+', '-' ); + name = name.Replace( '`', '_' ); + + XmlElement childElem = getNamedChild( allChildren, name ); + + if( childElem != null ) + { + object childObj = Deserialize( childElem, childFi.FieldType, obj ); + + childFi.SetValue( obj, childObj ); + } + } + } + + return obj; + } + + private object DeserializeList( XmlElement elem, Type type, IList list ) + { + XmlNodeList arrNodeList = elem.ChildNodes; + + Type t = list.GetType(); + + Type[] genT = t.GetGenericArguments(); + + Debug.Assert( genT.Length == 1 ); + + for( int i = 0; i < arrNodeList.Count; ++i ) + { + if( arrNodeList.Item( i ) is XmlElement ) + { + XmlElement arrElem = (XmlElement)arrNodeList.Item( i ); + + list.Add( Deserialize( arrElem, genT[0] ) ); + } + } + + return list; + } + + private object DeserializeArray( XmlElement elem, Type type ) + { + Type typeElem = type.GetElementType(); + + string refString = elem.GetAttribute( "ref" ); + int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1; + + XmlNodeList arrNodeList = elem.ChildNodes; + + int length = arrNodeList.Count; + + Array arr = createArray( typeElem, refInt, length ); + + for( int i = 0; i < arr.Length; ++i ) + { + if( arrNodeList.Item( i ) is XmlElement ) + { + XmlElement arrElem = (XmlElement)arrNodeList.Item( i ); + + arr.SetValue( Deserialize( arrElem, typeElem ), i ); + } + } + + return arr; + } + + private object createObject( string typename, int refInt ) + { + Type type = Type.GetType( typename ); + + return createObject( type, refInt ); + } + + private object createObject( Type type, int refInt ) + { + TypeCode tc = Type.GetTypeCode( type ); + + if( refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) + { + //lib.log.info( "Reusing object for {0}", refInt ); + return m_alreadySerialized[ refInt ]; + } + else + { + //lib.log.info( "Creating new object for {0}", refInt ); + object obj = Activator.CreateInstance( type ); + + if( refInt > 0 ) + { + m_alreadySerialized[ refInt ] = obj; + } + + return obj; + } + } + + private Array createArray( string elemTypename, int refInt, int length ) + { + Type elemType = Type.GetType( elemTypename ); + + return createArray( elemType, refInt, length ); + } + + private Array createArray( Type elemType, int refInt, int length ) + { + TypeCode elemTC = Type.GetTypeCode( elemType ); + + if( refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) + { + return (Array)m_alreadySerialized[ refInt ]; + } + else + { + Array arr = Array.CreateInstance( elemType, length ) ; + + m_alreadySerialized[ refInt ] = arr; + + return arr; + } + } + + private ObjectIDGenerator m_objectID = new ObjectIDGenerator(); + private Dictionary m_alreadySerialized = new Dictionary(); + + #endregion + + #region Serialize + + private string getTypeName( Type type ) + { + //Assembly ass = type.Assembly; + + //string assName = ass.GetName().Name; + + return type.FullName; // + ", " + assName; + } + + public void Serialize( Stream stream, object root ) + { + //lib.log.info( "Serialize( Stream stream, object root ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + + m_alreadySerialized.Clear(); + m_objectID = new ObjectIDGenerator(); + + XmlTextWriter writer = new XmlTextWriter( stream, System.Text.Encoding.ASCII ); + + writer.Formatting = Formatting.Indented; + + Serialize( writer, root ); + + //Rely on the parent closing the stream. + //writer.Close(); + writer.Flush(); + + //lib.log.info( "Serialize END ( Stream stream, object root ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + } + + private void Serialize( XmlWriter writer, object root ) + { + //writer.WriteStartDocument(); + Serialize( writer, root, "root" ); + //writer.WriteEndDocument(); + } + + private void Serialize( XmlWriter writer, object root, string name ) + { + writer.WriteStartElement( name ); + + if( root != null ) + { + Type type = root.GetType(); + + TypeCode typeCode = Type.GetTypeCode( type ); + + if( typeCode != TypeCode.Object ) + { + SerializeConcrete( writer, root ); + } + else + { + if( !type.IsArray ) + { + SerializeObject( writer, root ); + } + else + { + SerializeArray( writer, root ); + } + } + } + else + { + writer.WriteAttributeString( "v", "null" ); + } + + writer.WriteEndElement(); + } + + private void SerializeConcrete( XmlWriter writer, object root ) + { + //TODO: Only write this out if debugging. + //writer.WriteAttributeString( "t", getTypeName( root.GetType() ) ); + writer.WriteAttributeString( "v", root.ToString() ); + } + + private void SerializeObject( XmlWriter writer, object root ) + { + writer.WriteAttributeString( "t", getTypeName( root.GetType() ) ); + + /* + if( root is IList ) + { + var list = root as IList; + + Type t = root.GetType(); + + Type[] genT = t.GetGenericArguments(); + } + */ + + bool first; + + long refInt = m_objectID.GetId( root, out first ); + + writer.WriteAttributeString( "ref", refInt.ToString() ); + + if( first ) + { + m_alreadySerialized[ refInt ] = root; + + Type type = root.GetType(); + + //* + Type typeISerializable = typeof( ISerializable ); + + if( root is ISerializable ) // type.IsSubclassOf( typeISerializable ) ) + { + ISerializable ser = root as ISerializable; + + var serInfo = new SerializationInfo( type, new FormatterConverter() ); + + ser.GetObjectData( serInfo, Context ); + + //var serEnum = ; + + foreach( var serMember in serInfo ) + { + String name = serMember.Name; + + name = name.Replace( '+', '-' ); + name = name.Replace( '`', '_' ); + + Serialize( writer, serMember.Value, name ); + } + + //var sc = new SerializationContext( + + //ser.GetObjectData( + } + else + //*/ + { + MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type, Context ); + + for( int i = 0; i < miArr.Length; ++i ) + { + FieldInfo childFi = (FieldInfo)miArr[ i ]; + + object[] objs = childFi.GetCustomAttributes( typeof( NonSerializedAttribute ), true ); + + if( objs.Length > 0 ) + { + continue; + } + + String name = childFi.Name; + + name = name.Replace( '+', '-' ); + name = name.Replace( '`', '_' ); + + Serialize( writer, childFi.GetValue( root ), name ); + } + } + } + } + + private void SerializeArray( XmlWriter writer, object root ) + { + Array arr = (Array)root; + + Type typeElem = arr.GetType().GetElementType(); + + writer.WriteAttributeString( "t", getTypeName( typeElem ) ); + + bool first; + + long refInt = m_objectID.GetId( root, out first ); + + writer.WriteAttributeString( "ref", refInt.ToString() ); + + if( first ) + { + m_alreadySerialized[ refInt ] = root; + + + for( int i = 0; i < arr.Length; ++i ) + { + Serialize( writer, arr.GetValue( i ), "i" + i.ToString() ); + } + } + } + #endregion +} + +} diff --git a/import.txt b/import.txt deleted file mode 100644 index e69de29..0000000 diff --git a/res/Resource.cs b/res/Resource.cs new file mode 100644 index 0000000..e3b9e1d --- /dev/null +++ b/res/Resource.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +//using System.Threading.Tasks; +using System.Diagnostics; +using System.Reflection; + +namespace res +{ + +[Serializable] +public class Ref : lib.I_Serialize +{ + public string filename { get { return m_filename; } } + + //For construction + public Ref() + { + } + + public Ref( string filename ) + { + m_filename = filename; + } + + virtual public void OnSerialize() + { + } + + virtual public void OnDeserialize( object enclosing ) + { + } + + virtual public void OnChange() + { + } + + private string m_filename; +} + +[Serializable] +public class Ref : Ref +{ + public T res{ get{ return m_res; } set{ m_res = value; } } + + //For construction + public Ref() + { + } + + public Ref( string filename ) + : base( filename ) + { + } + + public Ref( string filename, T res ) : base( filename ) + { + m_res = res; + } + + [NonSerialized] + private T m_res; +} + + + + +public class Resource +{ + static public Mgr mgr; + +} + + +/* +public class Loader +{ + static public T load( string filename ) + { + Debug.Assert( false, "Specialize Loader for your type for file" ); + return default(T); + } +} +*/ +public delegate Ref Load( string filename ); +public delegate Ref LoadType( string filename, Type t ); + + +public class Mgr +{ + + + static public void startup() + { + Resource.mgr = new Mgr(); + } + + static public void register( Load loader ) + { + Debug.Assert( !Resource.mgr.m_loaders.ContainsKey( typeof( T ) ) ); + Resource.mgr.m_loaders[ typeof( T ) ] = loader; + } + + static public void registerSub( Load loaderOfType ) + { + + Type[] typeParams = new Type[1]; + foreach( var mi in typeof( T ).GetMethods() ) + { + if( mi.Name == "res_load" && mi.IsGenericMethod ) + { + foreach( var ass in AppDomain.CurrentDomain.GetAssemblies() ) + { + foreach( var t in ass.GetTypes() ) + { + if( t.IsSubclassOf( typeof( T ) ) ) + { + typeParams[0] = t; + var mi_ng = mi.MakeGenericMethod( typeParams ); + Resource.mgr.m_loaders[ t ] = (Load)Delegate.CreateDelegate( typeof(Load), mi_ng ); + } + } + } + return; + } + } + } + + static public Ref load( string filename ) where T : class + { + Load loader; + Resource.mgr.m_loaders.TryGetValue( typeof( T ), out loader ); + + if( loader != null ) + { + var rf_raw = loader( filename ); + Ref rf = rf_raw as Ref; + return rf; + } + + return new Ref( filename ); + } + + static public Ref load( string filename, Type t ) + { + Load loader; + Resource.mgr.m_loaders.TryGetValue( t, out loader ); + + if( loader != null ) + { + var rf_raw = loader( filename ); + return rf_raw; + } + + return new Ref( filename ); + } + + private Dictionary m_loaders = new Dictionary(); + //private Dictionary m_loadersOfType = new Dictionary(); +} + + + + + +}