diff --git a/Utilities.cs b/Utilities.cs index 18a70ff..8604dba 100644 --- a/Utilities.cs +++ b/Utilities.cs @@ -1,845 +1,849 @@ -// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -// -// Copyright (c) 2010-2012 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -#pragma warning disable SA1405 // Debug.Assert must provide message text -using att; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; -using System.Threading; - -namespace lib -{ - /// - /// Utility class. - /// - public static class Util - { - - /* - #if XENKO_PLATFORM_UWP - public static unsafe void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) - { - Interop.memcpy((void*)dest, (void*)src, sizeInBytesToCopy); - } - #else - #if XENKO_PLATFORM_WINDOWS_DESKTOP - private const string MemcpyDll = "msvcrt.dll"; - #elif XENKO_PLATFORM_ANDROID - private const string MemcpyDll = "libc.so"; - #elif XENKO_PLATFORM_UNIX - // We do not specifiy the .so extension as libc.so on Linux - // is actually not a .so files but a script. Using just libc - // will automatically find the corresponding .so. - private const string MemcpyDll = "libc"; - #elif XENKO_PLATFORM_IOS - private const string MemcpyDll = ObjCRuntime.Constants.SystemLibrary; - #else - # error Unsupported platform - #endif - [DllImport(MemcpyDll, EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] - #if !XENKO_RUNTIME_CORECLR - [SuppressUnmanagedCodeSecurity] - #endif - private static extern IntPtr CopyMemory(IntPtr dest, IntPtr src, ulong sizeInBytesToCopy); - - /// - /// Copy memory. - /// - /// The destination memory location - /// The source memory location. - /// The count. - public static void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) - { - CopyMemory(dest, src, (ulong)sizeInBytesToCopy); - } - #endif - */ - - - - public static void checkAndAddDirectory( string path ) - { - if( !Directory.Exists( path ) ) - { - lib.Log.info( $"Creating directory {path}" ); - Directory.CreateDirectory( path ); - } - - } - - - /// - /// Compares two block of memory. - /// - /// The pointer to compare from. - /// The pointer to compare against. - /// The size in bytes to compare. - /// True if the buffers are equivalent, false otherwise. - public static unsafe bool CompareMemory( IntPtr from, IntPtr against, int sizeToCompare ) - { - var pSrc = (byte*)from; - var pDst = (byte*)against; - - // Compare 8 bytes. - var numberOf = sizeToCompare >> 3; - while( numberOf > 0 ) - { - if( *(long*)pSrc != *(long*)pDst ) - return false; - pSrc += 8; - pDst += 8; - numberOf--; - } - - // Compare remaining bytes. - numberOf = sizeToCompare & 7; - while( numberOf > 0 ) - { - if( *pSrc != *pDst ) - return false; - pSrc++; - pDst++; - numberOf--; - } - - return true; - } - - /// - /// Clears the memory. - /// - /// The dest. - /// The value. - /// The size in bytes to clear. - public static void ClearMemory( IntPtr dest, byte value, int sizeInBytesToClear ) - { - unsafe - { - Interop.memset( (void*)dest, value, sizeInBytesToClear ); - } - } - - /// - /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. - /// - /// a struct to evaluate - /// sizeof this struct - public static int SizeOf() where T : struct - { - return Interop.SizeOf(); - } - - /// - /// Return the sizeof an array of struct. Equivalent to sizeof operator but works on generics too. - /// - /// a struct - /// The array of struct to evaluate. - /// sizeof in bytes of this array of struct - public static int SizeOf( T[] array ) where T : struct - { - return array == null ? 0 : array.Length * Interop.SizeOf(); - } - - /// - /// Pins the specified source and call an action with the pinned pointer. - /// - /// The type of the structure to pin - /// The source. - /// The pin action to perform on the pinned pointer. - public static void Pin( ref T source, Action pinAction ) where T : struct - { - unsafe - { - pinAction( (IntPtr)Interop.Fixed( ref source ) ); - } - } - - /// - /// Pins the specified source and call an action with the pinned pointer. - /// - /// The type of the structure to pin - /// The source array. - /// The pin action to perform on the pinned pointer. - public static void Pin( T[] source, [NotNull] Action pinAction ) where T : struct - { - unsafe - { - pinAction( source == null ? IntPtr.Zero : (IntPtr)Interop.Fixed( source ) ); - } - } - - /// - /// Covnerts a structured array to an equivalent byte array. - /// - /// The source. - /// The byte array. - public static byte[] ToByteArray( T[] source ) where T : struct - { - if( source == null ) - return null; - - var buffer = new byte[SizeOf() * source.Length]; - - if( source.Length == 0 ) - return buffer; - - unsafe - { - fixed ( void* pBuffer = buffer ) - Interop.Write( pBuffer, source, 0, source.Length ); - } - return buffer; - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read - /// Memory location to read from. - /// The data read from the memory location - public static T Read( IntPtr source ) where T : struct - { - unsafe - { - return Interop.ReadInline( (void*)source ); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read - /// Memory location to read from. - /// The data write to. - [MethodImpl( MethodImplOptions.AggressiveInlining )] - public static void Read( IntPtr source, ref T data ) where T : struct - { - unsafe - { - Interop.CopyInline( ref data, (void*)source ); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read - /// Memory location to read from. - /// The data write to. - public static void ReadOut( IntPtr source, out T data ) where T : struct - { - unsafe - { - Interop.CopyInlineOut( out data, (void*)source ); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read - /// Memory location to read from. - /// The data write to. - /// source pointer + sizeof(T) - public static IntPtr ReadAndPosition( IntPtr source, ref T data ) where T : struct - { - unsafe - { - return (IntPtr)Interop.Read( (void*)source, ref data ); - } - } - - /// - /// Reads the specified array T[] data from a memory location. - /// - /// Type of a data to read - /// Memory location to read from. - /// The data write to. - /// The offset in the array to write to. - /// The number of T element to read from the memory location - /// source pointer + sizeof(T) * count - public static IntPtr Read( IntPtr source, T[] data, int offset, int count ) where T : struct - { - unsafe - { - return (IntPtr)Interop.Read( (void*)source, data, offset, count ); - } - } - - /// - /// Writes the specified T data to a memory location. - /// - /// Type of a data to write - /// Memory location to write to. - /// The data to write. - [MethodImpl( MethodImplOptions.AggressiveInlining )] - public static void Write( IntPtr destination, ref T data ) where T : struct - { - unsafe - { - Interop.CopyInline( (void*)destination, ref data ); - } - } - - /// - /// Writes the specified T data to a memory location. - /// - /// Type of a data to write - /// Memory location to write to. - /// The data to write. - /// destination pointer + sizeof(T) - public static IntPtr WriteAndPosition( IntPtr destination, ref T data ) where T : struct - { - unsafe - { - return (IntPtr)Interop.Write( (void*)destination, ref data ); - } - } - - /// - /// Writes the specified array T[] data to a memory location. - /// - /// Type of a data to write - /// Memory location to write to. - /// The array of T data to write. - /// The offset in the array to read from. - /// The number of T element to write to the memory location - public static void Write( byte[] destination, T[] data, int offset, int count ) where T : struct - { - unsafe - { - fixed ( void* pDest = destination ) - { - Write( (IntPtr)pDest, data, offset, count ); - } - } - } - - /// - /// Writes the specified array T[] data to a memory location. - /// - /// Type of a data to write - /// Memory location to write to. - /// The array of T data to write. - /// The offset in the array to read from. - /// The number of T element to write to the memory location - /// destination pointer + sizeof(T) * count - public static IntPtr Write( IntPtr destination, T[] data, int offset, int count ) where T : struct - { - unsafe - { - return (IntPtr)Interop.Write( (void*)destination, data, offset, count ); - } - } - - /// - /// Allocate an aligned memory buffer. - /// - /// Size of the buffer to allocate. - /// Alignment, a positive value which is a power of 2. 16 bytes by default. - /// A pointer to a buffer aligned. - /// - /// To free this buffer, call - /// - public static unsafe IntPtr AllocateMemory( int sizeInBytes, int align = 16 ) - { - var mask = align - 1; - if( ( align & mask ) != 0 ) - { - throw new ArgumentException( "Alignment is not power of 2", nameof( align ) ); - } - var memPtr = Marshal.AllocHGlobal(sizeInBytes + mask + sizeof(void*)); - var ptr = (byte*)((ulong)(memPtr.ToInt32() + sizeof(void*) + mask) & ~(ulong)mask); - ( (IntPtr*)ptr )[-1] = memPtr; - return new IntPtr( ptr ); - } - - /// - /// Allocate an aligned memory buffer and clear it with a specified value (0 by defaault). - /// - /// Size of the buffer to allocate. - /// Default value used to clear the buffer. - /// Alignment, 16 bytes by default. - /// A pointer to a buffer aligned. - /// - /// To free this buffer, call - /// - public static IntPtr AllocateClearedMemory( int sizeInBytes, byte clearValue = 0, int align = 16 ) - { - var ptr = AllocateMemory(sizeInBytes, align); - ClearMemory( ptr, clearValue, sizeInBytes ); - return ptr; - } - - /// - /// Determines whether the specified memory pointer is aligned in memory. - /// - /// The memory pointer. - /// The align. - /// true if the specified memory pointer is aligned in memory; otherwise, false. - public static bool IsMemoryAligned( IntPtr memoryPtr, int align = 16 ) - { - return ( memoryPtr.ToInt64() & ( align - 1 ) ) == 0; - } - - /// - /// Allocate an aligned memory buffer. - /// - /// - /// The buffer must have been allocated with - /// - public static unsafe void FreeMemory( IntPtr alignedBuffer ) - { - Marshal.FreeHGlobal( ( (IntPtr*)alignedBuffer )[-1] ); - } - - /// - /// If non-null, disposes the specified object and set it to null, otherwise do nothing. - /// - /// The disposable. - public static void Dispose( ref T disposable ) where T : class, IDisposable - { - if( disposable != null ) - { - disposable.Dispose(); - disposable = null; - } - } - - /// - /// String helper join method to display an array of object as a single string. - /// - /// The separator. - /// The array. - /// a string with array elements serparated by the seperator - [NotNull] - public static string Join( string separator, T[] array ) - { - var text = new StringBuilder(); - if( array != null ) - { - for( var i = 0; i < array.Length; i++ ) - { - if( i > 0 ) - text.Append( separator ); - text.Append( array[i] ); - } - } - return text.ToString(); - } - - /// - /// String helper join method to display an enumrable of object as a single string. - /// - /// The separator. - /// The enumerable. - /// a string with array elements serparated by the seperator - [NotNull] - public static string Join( string separator, [NotNull] IEnumerable elements ) - { - var elementList = new List(); - foreach( var element in elements ) - elementList.Add( element.ToString() ); - - var text = new StringBuilder(); - for( var i = 0; i < elementList.Count; i++ ) - { - var element = elementList[i]; - if( i > 0 ) - text.Append( separator ); - text.Append( element ); - } - return text.ToString(); - } - - /// - /// String helper join method to display an enumrable of object as a single string. - /// - /// The separator. - /// The enumerable. - /// a string with array elements serparated by the seperator - [NotNull] - public static string Join( string separator, [NotNull] IEnumerator elements ) - { - var elementList = new List(); - while( elements.MoveNext() ) - elementList.Add( elements.Current.ToString() ); - - var text = new StringBuilder(); - for( var i = 0; i < elementList.Count; i++ ) - { - var element = elementList[i]; - if( i > 0 ) - text.Append( separator ); - text.Append( element ); - } - return text.ToString(); - } - - /// - /// Read stream to a byte[] buffer - /// - /// input stream - /// a byte[] buffer - [NotNull] - public static byte[] ReadStream( [NotNull] Stream stream ) - { - var readLength = 0; - return ReadStream( stream, ref readLength ); - } - - /// - /// Read stream to a byte[] buffer - /// - /// input stream - /// length to read - /// a byte[] buffer - [NotNull] - public static byte[] ReadStream( [NotNull] Stream stream, ref int readLength ) - { - System.Diagnostics.Debug.Assert( stream != null ); - System.Diagnostics.Debug.Assert( stream.CanRead ); - var num = readLength; - System.Diagnostics.Debug.Assert( num <= ( stream.Length - stream.Position ) ); - if( num == 0 ) - readLength = (int)( stream.Length - stream.Position ); - num = readLength; - - System.Diagnostics.Debug.Assert( num >= 0 ); - if( num == 0 ) - return new byte[0]; - - var buffer = new byte[num]; - var bytesRead = 0; - if( num > 0 ) - { - do - { - bytesRead += stream.Read( buffer, bytesRead, readLength - bytesRead ); - } while( bytesRead < readLength ); - } - return buffer; - } - - /// - /// Computes a hashcode for a dictionary. - /// - /// Hashcode for the list. - public static int GetHashCode( IDictionary dict ) - { - if( dict == null ) - return 0; - - var hashCode = 0; - foreach( DictionaryEntry keyValue in dict ) - { - hashCode = ( hashCode * 397 ) ^ keyValue.Key.GetHashCode(); - hashCode = ( hashCode * 397 ) ^ ( keyValue.Value?.GetHashCode() ?? 0 ); - } - return hashCode; - } - - /// - /// Computes a hashcode for an enumeration - /// - /// An enumerator. - /// Hashcode for the list. - public static int GetHashCode( IEnumerable it ) - { - if( it == null ) - return 0; - - var hashCode = 0; - foreach( var current in it ) - { - hashCode = ( hashCode * 397 ) ^ ( current?.GetHashCode() ?? 0 ); - } - return hashCode; - } - - /// - /// Computes a hashcode for an enumeration - /// - /// An enumerator. - /// Hashcode for the list. - public static int GetHashCode( IEnumerator it ) - { - if( it == null ) - return 0; - - var hashCode = 0; - while( it.MoveNext() ) - { - var current = it.Current; - hashCode = ( hashCode * 397 ) ^ ( current?.GetHashCode() ?? 0 ); - } - return hashCode; - } - - /// - /// Compares two collection, element by elements. - /// - /// A "from" enumerator. - /// A "to" enumerator. - /// True if lists are identical. False otherwise. - public static bool Compare( IEnumerable left, IEnumerable right ) - { - if( ReferenceEquals( left, right ) ) - return true; - if( ReferenceEquals( left, null ) || ReferenceEquals( right, null ) ) - return false; - - return Compare( left.GetEnumerator(), right.GetEnumerator() ); - } - - /// - /// Compares two collection, element by elements. - /// - /// A "from" enumerator. - /// A "to" enumerator. - /// True if lists are identical. False otherwise. - public static bool Compare( IEnumerator leftIt, IEnumerator rightIt ) - { - if( ReferenceEquals( leftIt, rightIt ) ) - return true; - if( ReferenceEquals( leftIt, null ) || ReferenceEquals( rightIt, null ) ) - return false; - - bool hasLeftNext; - bool hasRightNext; - while( true ) - { - hasLeftNext = leftIt.MoveNext(); - hasRightNext = rightIt.MoveNext(); - if( !hasLeftNext || !hasRightNext ) - break; - - if( !Equals( leftIt.Current, rightIt.Current ) ) - return false; - } - - // If there is any left element - if( hasLeftNext != hasRightNext ) - return false; - - return true; - } - - /// - /// Compares two collection, element by elements. - /// - /// The collection to compare from. - /// The colllection to compare to. - /// True if lists are identical (but no necessarely of the same time). False otherwise. - public static bool Compare( IDictionary first, IDictionary second ) - { - if( ReferenceEquals( first, second ) ) - return true; - if( ReferenceEquals( first, null ) || ReferenceEquals( second, null ) ) - return false; - if( first.Count != second.Count ) - return false; - - var comparer = EqualityComparer.Default; - - foreach( var keyValue in first ) - { - TValue secondValue; - if( !second.TryGetValue( keyValue.Key, out secondValue ) ) - return false; - if( !comparer.Equals( keyValue.Value, secondValue ) ) - return false; - } - - // Check that all keys in second are in first - return second.Keys.All( first.ContainsKey ); - } - - public static bool Compare( T[] left, T[] right ) - { - if( ReferenceEquals( left, right ) ) - return true; - if( ReferenceEquals( left, null ) || ReferenceEquals( right, null ) ) - return false; - - if( left.Length != right.Length ) - return false; - - var comparer = EqualityComparer.Default; - for( var i = 0; i < left.Length; ++i ) - { - if( !comparer.Equals( left[i], right[i] ) ) - return false; - } - - return true; - } - - /// - /// Compares two collection, element by elements. - /// - /// The collection to compare from. - /// The colllection to compare to. - /// True if lists are identical (but no necessarely of the same time). False otherwise. - public static bool Compare( ICollection left, ICollection right ) - { - if( ReferenceEquals( left, right ) ) - return true; - if( ReferenceEquals( left, null ) || ReferenceEquals( right, null ) ) - return false; - - if( left.Count != right.Count ) - return false; - - var count = 0; - var leftIt = left.GetEnumerator(); - var rightIt = right.GetEnumerator(); - var comparer = EqualityComparer.Default; - while( leftIt.MoveNext() && rightIt.MoveNext() ) - { - if( !comparer.Equals( leftIt.Current, rightIt.Current ) ) - return false; - count++; - } - - // Just double check to make sure that the iterator actually returns - // the exact number of elements - if( count != left.Count ) - return false; - - return true; - } - - /// - /// Swaps the value between two references. - /// - /// Type of a data to swap. - /// The left value. - /// The right value. - public static void Swap( ref T left, ref T right ) - { - var temp = left; - left = right; - right = temp; - } - - /// - /// Suspends current thread for a . - /// - /// The duration of sleep. - public static void Sleep( TimeSpan sleepTime ) - { - var ms = (long)sleepTime.TotalMilliseconds; - if( ms < 0 || ms > int.MaxValue ) - { - throw new ArgumentOutOfRangeException( nameof( sleepTime ), "Sleep time must be a duration less than '2^31 - 1' milliseconds." ); - } - // MH PORTED NativeInvoke.Sleep((int)ms); - Thread.Sleep( (int)ms ); - } - - /// - /// Suspends current thread for a . - /// - /// The duration of sleep in milliseconds. - public static void Sleep( int sleepTimeInMillis ) - { - // MH PORTED NativeInvoke.Sleep(sleepTimeInMillis); - Thread.Sleep( sleepTimeInMillis ); - } - - /// - /// Writes the specified T data to a memory location. - /// - /// Type of a data to write - /// Memory location to write to. - /// The data to write. - internal static void UnsafeWrite( IntPtr destination, ref T data ) - { - unsafe - { - Interop.CopyInline( (void*)destination, ref data ); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read - /// Memory location to read from. - /// The data write to. - internal static void UnsafeReadOut( IntPtr source, out T data ) - { - unsafe - { - Interop.CopyInlineOut( out data, (void*)source ); - } - } - - /// - /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. - /// - /// a struct to evaluate - /// sizeof this struct - internal static int UnsafeSizeOf() - { - return Interop.SizeOf(); - } - - /// - /// Linq assisted full tree iteration and collection in a single line. - /// Warning, could be slow. - /// - /// The type to iterate. - /// The root item - /// The function to retrieve a child - public static IEnumerable IterateTree( T root, Func> childrenF ) - { - var q = new List { root }; - while( q.Any() ) - { - var c = q[0]; - q.RemoveAt( 0 ); - q.AddRange( childrenF( c ) ?? Enumerable.Empty() ); - yield return c; - } - } - - /// - /// Converts a raw time to a . - /// - /// The delta. - /// The . - public static TimeSpan ConvertRawToTimestamp( long delta ) - { - return new TimeSpan( delta == 0 ? 0 : ( delta * TimeSpan.TicksPerSecond ) / Stopwatch.Frequency ); - } - } -} +// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. +// +// Copyright (c) 2010-2012 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#pragma warning disable SA1405 // Debug.Assert must provide message text +using att; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using System.Threading; + +namespace lib +{ + /// + /// Utility class. + /// + public static class Util + { + + /* + #if XENKO_PLATFORM_UWP + public static unsafe void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) + { + Interop.memcpy((void*)dest, (void*)src, sizeInBytesToCopy); + } + #else + #if XENKO_PLATFORM_WINDOWS_DESKTOP + private const string MemcpyDll = "msvcrt.dll"; + #elif XENKO_PLATFORM_ANDROID + private const string MemcpyDll = "libc.so"; + #elif XENKO_PLATFORM_UNIX + // We do not specifiy the .so extension as libc.so on Linux + // is actually not a .so files but a script. Using just libc + // will automatically find the corresponding .so. + private const string MemcpyDll = "libc"; + #elif XENKO_PLATFORM_IOS + private const string MemcpyDll = ObjCRuntime.Constants.SystemLibrary; + #else + # error Unsupported platform + #endif + [DllImport(MemcpyDll, EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] + #if !XENKO_RUNTIME_CORECLR + [SuppressUnmanagedCodeSecurity] + #endif + private static extern IntPtr CopyMemory(IntPtr dest, IntPtr src, ulong sizeInBytesToCopy); + + /// + /// Copy memory. + /// + /// The destination memory location + /// The source memory location. + /// The count. + public static void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) + { + CopyMemory(dest, src, (ulong)sizeInBytesToCopy); + } + #endif + */ + + + + public static void checkAndAddDirectory( string path ) + { + if( !Directory.Exists( path ) ) + { + lib.Log.info( $"Creating directory {path}" ); + Directory.CreateDirectory( path ); + } + else + { + lib.Log.debug( $"{path} already exists." ); + } + + } + + + /// + /// Compares two block of memory. + /// + /// The pointer to compare from. + /// The pointer to compare against. + /// The size in bytes to compare. + /// True if the buffers are equivalent, false otherwise. + public static unsafe bool CompareMemory( IntPtr from, IntPtr against, int sizeToCompare ) + { + var pSrc = (byte*)from; + var pDst = (byte*)against; + + // Compare 8 bytes. + var numberOf = sizeToCompare >> 3; + while( numberOf > 0 ) + { + if( *(long*)pSrc != *(long*)pDst ) + return false; + pSrc += 8; + pDst += 8; + numberOf--; + } + + // Compare remaining bytes. + numberOf = sizeToCompare & 7; + while( numberOf > 0 ) + { + if( *pSrc != *pDst ) + return false; + pSrc++; + pDst++; + numberOf--; + } + + return true; + } + + /// + /// Clears the memory. + /// + /// The dest. + /// The value. + /// The size in bytes to clear. + public static void ClearMemory( IntPtr dest, byte value, int sizeInBytesToClear ) + { + unsafe + { + Interop.memset( (void*)dest, value, sizeInBytesToClear ); + } + } + + /// + /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. + /// + /// a struct to evaluate + /// sizeof this struct + public static int SizeOf() where T : struct + { + return Interop.SizeOf(); + } + + /// + /// Return the sizeof an array of struct. Equivalent to sizeof operator but works on generics too. + /// + /// a struct + /// The array of struct to evaluate. + /// sizeof in bytes of this array of struct + public static int SizeOf( T[] array ) where T : struct + { + return array == null ? 0 : array.Length * Interop.SizeOf(); + } + + /// + /// Pins the specified source and call an action with the pinned pointer. + /// + /// The type of the structure to pin + /// The source. + /// The pin action to perform on the pinned pointer. + public static void Pin( ref T source, Action pinAction ) where T : struct + { + unsafe + { + pinAction( (IntPtr)Interop.Fixed( ref source ) ); + } + } + + /// + /// Pins the specified source and call an action with the pinned pointer. + /// + /// The type of the structure to pin + /// The source array. + /// The pin action to perform on the pinned pointer. + public static void Pin( T[] source, [NotNull] Action pinAction ) where T : struct + { + unsafe + { + pinAction( source == null ? IntPtr.Zero : (IntPtr)Interop.Fixed( source ) ); + } + } + + /// + /// Covnerts a structured array to an equivalent byte array. + /// + /// The source. + /// The byte array. + public static byte[] ToByteArray( T[] source ) where T : struct + { + if( source == null ) + return null; + + var buffer = new byte[SizeOf() * source.Length]; + + if( source.Length == 0 ) + return buffer; + + unsafe + { + fixed ( void* pBuffer = buffer ) + Interop.Write( pBuffer, source, 0, source.Length ); + } + return buffer; + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read + /// Memory location to read from. + /// The data read from the memory location + public static T Read( IntPtr source ) where T : struct + { + unsafe + { + return Interop.ReadInline( (void*)source ); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read + /// Memory location to read from. + /// The data write to. + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public static void Read( IntPtr source, ref T data ) where T : struct + { + unsafe + { + Interop.CopyInline( ref data, (void*)source ); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read + /// Memory location to read from. + /// The data write to. + public static void ReadOut( IntPtr source, out T data ) where T : struct + { + unsafe + { + Interop.CopyInlineOut( out data, (void*)source ); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read + /// Memory location to read from. + /// The data write to. + /// source pointer + sizeof(T) + public static IntPtr ReadAndPosition( IntPtr source, ref T data ) where T : struct + { + unsafe + { + return (IntPtr)Interop.Read( (void*)source, ref data ); + } + } + + /// + /// Reads the specified array T[] data from a memory location. + /// + /// Type of a data to read + /// Memory location to read from. + /// The data write to. + /// The offset in the array to write to. + /// The number of T element to read from the memory location + /// source pointer + sizeof(T) * count + public static IntPtr Read( IntPtr source, T[] data, int offset, int count ) where T : struct + { + unsafe + { + return (IntPtr)Interop.Read( (void*)source, data, offset, count ); + } + } + + /// + /// Writes the specified T data to a memory location. + /// + /// Type of a data to write + /// Memory location to write to. + /// The data to write. + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public static void Write( IntPtr destination, ref T data ) where T : struct + { + unsafe + { + Interop.CopyInline( (void*)destination, ref data ); + } + } + + /// + /// Writes the specified T data to a memory location. + /// + /// Type of a data to write + /// Memory location to write to. + /// The data to write. + /// destination pointer + sizeof(T) + public static IntPtr WriteAndPosition( IntPtr destination, ref T data ) where T : struct + { + unsafe + { + return (IntPtr)Interop.Write( (void*)destination, ref data ); + } + } + + /// + /// Writes the specified array T[] data to a memory location. + /// + /// Type of a data to write + /// Memory location to write to. + /// The array of T data to write. + /// The offset in the array to read from. + /// The number of T element to write to the memory location + public static void Write( byte[] destination, T[] data, int offset, int count ) where T : struct + { + unsafe + { + fixed ( void* pDest = destination ) + { + Write( (IntPtr)pDest, data, offset, count ); + } + } + } + + /// + /// Writes the specified array T[] data to a memory location. + /// + /// Type of a data to write + /// Memory location to write to. + /// The array of T data to write. + /// The offset in the array to read from. + /// The number of T element to write to the memory location + /// destination pointer + sizeof(T) * count + public static IntPtr Write( IntPtr destination, T[] data, int offset, int count ) where T : struct + { + unsafe + { + return (IntPtr)Interop.Write( (void*)destination, data, offset, count ); + } + } + + /// + /// Allocate an aligned memory buffer. + /// + /// Size of the buffer to allocate. + /// Alignment, a positive value which is a power of 2. 16 bytes by default. + /// A pointer to a buffer aligned. + /// + /// To free this buffer, call + /// + public static unsafe IntPtr AllocateMemory( int sizeInBytes, int align = 16 ) + { + var mask = align - 1; + if( ( align & mask ) != 0 ) + { + throw new ArgumentException( "Alignment is not power of 2", nameof( align ) ); + } + var memPtr = Marshal.AllocHGlobal(sizeInBytes + mask + sizeof(void*)); + var ptr = (byte*)((ulong)(memPtr.ToInt32() + sizeof(void*) + mask) & ~(ulong)mask); + ( (IntPtr*)ptr )[-1] = memPtr; + return new IntPtr( ptr ); + } + + /// + /// Allocate an aligned memory buffer and clear it with a specified value (0 by defaault). + /// + /// Size of the buffer to allocate. + /// Default value used to clear the buffer. + /// Alignment, 16 bytes by default. + /// A pointer to a buffer aligned. + /// + /// To free this buffer, call + /// + public static IntPtr AllocateClearedMemory( int sizeInBytes, byte clearValue = 0, int align = 16 ) + { + var ptr = AllocateMemory(sizeInBytes, align); + ClearMemory( ptr, clearValue, sizeInBytes ); + return ptr; + } + + /// + /// Determines whether the specified memory pointer is aligned in memory. + /// + /// The memory pointer. + /// The align. + /// true if the specified memory pointer is aligned in memory; otherwise, false. + public static bool IsMemoryAligned( IntPtr memoryPtr, int align = 16 ) + { + return ( memoryPtr.ToInt64() & ( align - 1 ) ) == 0; + } + + /// + /// Allocate an aligned memory buffer. + /// + /// + /// The buffer must have been allocated with + /// + public static unsafe void FreeMemory( IntPtr alignedBuffer ) + { + Marshal.FreeHGlobal( ( (IntPtr*)alignedBuffer )[-1] ); + } + + /// + /// If non-null, disposes the specified object and set it to null, otherwise do nothing. + /// + /// The disposable. + public static void Dispose( ref T disposable ) where T : class, IDisposable + { + if( disposable != null ) + { + disposable.Dispose(); + disposable = null; + } + } + + /// + /// String helper join method to display an array of object as a single string. + /// + /// The separator. + /// The array. + /// a string with array elements serparated by the seperator + [NotNull] + public static string Join( string separator, T[] array ) + { + var text = new StringBuilder(); + if( array != null ) + { + for( var i = 0; i < array.Length; i++ ) + { + if( i > 0 ) + text.Append( separator ); + text.Append( array[i] ); + } + } + return text.ToString(); + } + + /// + /// String helper join method to display an enumrable of object as a single string. + /// + /// The separator. + /// The enumerable. + /// a string with array elements serparated by the seperator + [NotNull] + public static string Join( string separator, [NotNull] IEnumerable elements ) + { + var elementList = new List(); + foreach( var element in elements ) + elementList.Add( element.ToString() ); + + var text = new StringBuilder(); + for( var i = 0; i < elementList.Count; i++ ) + { + var element = elementList[i]; + if( i > 0 ) + text.Append( separator ); + text.Append( element ); + } + return text.ToString(); + } + + /// + /// String helper join method to display an enumrable of object as a single string. + /// + /// The separator. + /// The enumerable. + /// a string with array elements serparated by the seperator + [NotNull] + public static string Join( string separator, [NotNull] IEnumerator elements ) + { + var elementList = new List(); + while( elements.MoveNext() ) + elementList.Add( elements.Current.ToString() ); + + var text = new StringBuilder(); + for( var i = 0; i < elementList.Count; i++ ) + { + var element = elementList[i]; + if( i > 0 ) + text.Append( separator ); + text.Append( element ); + } + return text.ToString(); + } + + /// + /// Read stream to a byte[] buffer + /// + /// input stream + /// a byte[] buffer + [NotNull] + public static byte[] ReadStream( [NotNull] Stream stream ) + { + var readLength = 0; + return ReadStream( stream, ref readLength ); + } + + /// + /// Read stream to a byte[] buffer + /// + /// input stream + /// length to read + /// a byte[] buffer + [NotNull] + public static byte[] ReadStream( [NotNull] Stream stream, ref int readLength ) + { + System.Diagnostics.Debug.Assert( stream != null ); + System.Diagnostics.Debug.Assert( stream.CanRead ); + var num = readLength; + System.Diagnostics.Debug.Assert( num <= ( stream.Length - stream.Position ) ); + if( num == 0 ) + readLength = (int)( stream.Length - stream.Position ); + num = readLength; + + System.Diagnostics.Debug.Assert( num >= 0 ); + if( num == 0 ) + return new byte[0]; + + var buffer = new byte[num]; + var bytesRead = 0; + if( num > 0 ) + { + do + { + bytesRead += stream.Read( buffer, bytesRead, readLength - bytesRead ); + } while( bytesRead < readLength ); + } + return buffer; + } + + /// + /// Computes a hashcode for a dictionary. + /// + /// Hashcode for the list. + public static int GetHashCode( IDictionary dict ) + { + if( dict == null ) + return 0; + + var hashCode = 0; + foreach( DictionaryEntry keyValue in dict ) + { + hashCode = ( hashCode * 397 ) ^ keyValue.Key.GetHashCode(); + hashCode = ( hashCode * 397 ) ^ ( keyValue.Value?.GetHashCode() ?? 0 ); + } + return hashCode; + } + + /// + /// Computes a hashcode for an enumeration + /// + /// An enumerator. + /// Hashcode for the list. + public static int GetHashCode( IEnumerable it ) + { + if( it == null ) + return 0; + + var hashCode = 0; + foreach( var current in it ) + { + hashCode = ( hashCode * 397 ) ^ ( current?.GetHashCode() ?? 0 ); + } + return hashCode; + } + + /// + /// Computes a hashcode for an enumeration + /// + /// An enumerator. + /// Hashcode for the list. + public static int GetHashCode( IEnumerator it ) + { + if( it == null ) + return 0; + + var hashCode = 0; + while( it.MoveNext() ) + { + var current = it.Current; + hashCode = ( hashCode * 397 ) ^ ( current?.GetHashCode() ?? 0 ); + } + return hashCode; + } + + /// + /// Compares two collection, element by elements. + /// + /// A "from" enumerator. + /// A "to" enumerator. + /// True if lists are identical. False otherwise. + public static bool Compare( IEnumerable left, IEnumerable right ) + { + if( ReferenceEquals( left, right ) ) + return true; + if( ReferenceEquals( left, null ) || ReferenceEquals( right, null ) ) + return false; + + return Compare( left.GetEnumerator(), right.GetEnumerator() ); + } + + /// + /// Compares two collection, element by elements. + /// + /// A "from" enumerator. + /// A "to" enumerator. + /// True if lists are identical. False otherwise. + public static bool Compare( IEnumerator leftIt, IEnumerator rightIt ) + { + if( ReferenceEquals( leftIt, rightIt ) ) + return true; + if( ReferenceEquals( leftIt, null ) || ReferenceEquals( rightIt, null ) ) + return false; + + bool hasLeftNext; + bool hasRightNext; + while( true ) + { + hasLeftNext = leftIt.MoveNext(); + hasRightNext = rightIt.MoveNext(); + if( !hasLeftNext || !hasRightNext ) + break; + + if( !Equals( leftIt.Current, rightIt.Current ) ) + return false; + } + + // If there is any left element + if( hasLeftNext != hasRightNext ) + return false; + + return true; + } + + /// + /// Compares two collection, element by elements. + /// + /// The collection to compare from. + /// The colllection to compare to. + /// True if lists are identical (but no necessarely of the same time). False otherwise. + public static bool Compare( IDictionary first, IDictionary second ) + { + if( ReferenceEquals( first, second ) ) + return true; + if( ReferenceEquals( first, null ) || ReferenceEquals( second, null ) ) + return false; + if( first.Count != second.Count ) + return false; + + var comparer = EqualityComparer.Default; + + foreach( var keyValue in first ) + { + TValue secondValue; + if( !second.TryGetValue( keyValue.Key, out secondValue ) ) + return false; + if( !comparer.Equals( keyValue.Value, secondValue ) ) + return false; + } + + // Check that all keys in second are in first + return second.Keys.All( first.ContainsKey ); + } + + public static bool Compare( T[] left, T[] right ) + { + if( ReferenceEquals( left, right ) ) + return true; + if( ReferenceEquals( left, null ) || ReferenceEquals( right, null ) ) + return false; + + if( left.Length != right.Length ) + return false; + + var comparer = EqualityComparer.Default; + for( var i = 0; i < left.Length; ++i ) + { + if( !comparer.Equals( left[i], right[i] ) ) + return false; + } + + return true; + } + + /// + /// Compares two collection, element by elements. + /// + /// The collection to compare from. + /// The colllection to compare to. + /// True if lists are identical (but no necessarely of the same time). False otherwise. + public static bool Compare( ICollection left, ICollection right ) + { + if( ReferenceEquals( left, right ) ) + return true; + if( ReferenceEquals( left, null ) || ReferenceEquals( right, null ) ) + return false; + + if( left.Count != right.Count ) + return false; + + var count = 0; + var leftIt = left.GetEnumerator(); + var rightIt = right.GetEnumerator(); + var comparer = EqualityComparer.Default; + while( leftIt.MoveNext() && rightIt.MoveNext() ) + { + if( !comparer.Equals( leftIt.Current, rightIt.Current ) ) + return false; + count++; + } + + // Just double check to make sure that the iterator actually returns + // the exact number of elements + if( count != left.Count ) + return false; + + return true; + } + + /// + /// Swaps the value between two references. + /// + /// Type of a data to swap. + /// The left value. + /// The right value. + public static void Swap( ref T left, ref T right ) + { + var temp = left; + left = right; + right = temp; + } + + /// + /// Suspends current thread for a . + /// + /// The duration of sleep. + public static void Sleep( TimeSpan sleepTime ) + { + var ms = (long)sleepTime.TotalMilliseconds; + if( ms < 0 || ms > int.MaxValue ) + { + throw new ArgumentOutOfRangeException( nameof( sleepTime ), "Sleep time must be a duration less than '2^31 - 1' milliseconds." ); + } + // MH PORTED NativeInvoke.Sleep((int)ms); + Thread.Sleep( (int)ms ); + } + + /// + /// Suspends current thread for a . + /// + /// The duration of sleep in milliseconds. + public static void Sleep( int sleepTimeInMillis ) + { + // MH PORTED NativeInvoke.Sleep(sleepTimeInMillis); + Thread.Sleep( sleepTimeInMillis ); + } + + /// + /// Writes the specified T data to a memory location. + /// + /// Type of a data to write + /// Memory location to write to. + /// The data to write. + internal static void UnsafeWrite( IntPtr destination, ref T data ) + { + unsafe + { + Interop.CopyInline( (void*)destination, ref data ); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read + /// Memory location to read from. + /// The data write to. + internal static void UnsafeReadOut( IntPtr source, out T data ) + { + unsafe + { + Interop.CopyInlineOut( out data, (void*)source ); + } + } + + /// + /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. + /// + /// a struct to evaluate + /// sizeof this struct + internal static int UnsafeSizeOf() + { + return Interop.SizeOf(); + } + + /// + /// Linq assisted full tree iteration and collection in a single line. + /// Warning, could be slow. + /// + /// The type to iterate. + /// The root item + /// The function to retrieve a child + public static IEnumerable IterateTree( T root, Func> childrenF ) + { + var q = new List { root }; + while( q.Any() ) + { + var c = q[0]; + q.RemoveAt( 0 ); + q.AddRange( childrenF( c ) ?? Enumerable.Empty() ); + yield return c; + } + } + + /// + /// Converts a raw time to a . + /// + /// The delta. + /// The . + public static TimeSpan ConvertRawToTimestamp( long delta ) + { + return new TimeSpan( delta == 0 ? 0 : ( delta * TimeSpan.TicksPerSecond ) / Stopwatch.Frequency ); + } + } +} diff --git a/Config.cs b/cfg/Config.cs similarity index 95% rename from Config.cs rename to cfg/Config.cs index 6af70b3..5dfc0f0 100644 --- a/Config.cs +++ b/cfg/Config.cs @@ -1,172 +1,172 @@ -using System; -using System.IO; -using System.Xml; -using System.Reflection; - -namespace lib -{ - - public class DescAttribute : Attribute - { - public string Desc { get; private set; } - - public DescAttribute( string desc ) - { - Desc = desc; - } - } - - [Serializable] - public class ConfigCfg : Config - { - public readonly bool writeOutTemplateFiles = true; - } - - - - [Serializable] - public class Config - { - /* - static public Config Load( string filename ) - { - return null; - } - */ - - static ConfigCfg s_cfg = new ConfigCfg(); - - static public void startup( string filename ) - { - res.Mgr.register( load ); - res.Mgr.registerSub( typeof( Config ) ); - - s_cfg = Config.load( filename ); - - } - - - #region SaveLoad - /* - static public res.Ref res_load( string filename ) - { - return new res.Ref( filename, load( filename ) ); - } - */ - - static public T res_load( string filename ) where T : Config - { - return 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( $"Exception while creating config {t.ToString()}, Msg {e.Message}" ); - } - - //cfg.SetFilename( filename ); - - if( s_cfg.writeOutTemplateFiles ) - { - var templateFile = $"templates/{filename}"; - - var dirName = Path.GetDirectoryName( templateFile ); - - lib.Util.checkAndAddDirectory( dirName ); - - lib.Log.info( $"Writing out template config of type {t.Name} in {templateFile}" ); - - Config.save( cfg, templateFile ); - } - } - - 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; } - - } -} - +using System; +using System.IO; +using System.Xml; +using System.Reflection; + +namespace lib +{ + + public class DescAttribute : Attribute + { + public string Desc { get; private set; } + + public DescAttribute( string desc ) + { + Desc = desc; + } + } + + [Serializable] + public class ConfigCfg : Config + { + public readonly bool writeOutTemplateFiles = true; + } + + + + [Serializable] + public class Config + { + /* + static public Config Load( string filename ) + { + return null; + } + */ + + static ConfigCfg s_cfg = new ConfigCfg(); + + static public void startup( string filename ) + { + res.Mgr.register( load ); + res.Mgr.registerSub( typeof( Config ) ); + + s_cfg = Config.load( filename ); + + } + + + #region SaveLoad + /* + static public res.Ref res_load( string filename ) + { + return new res.Ref( filename, load( filename ) ); + } + */ + + static public T res_load( string filename ) where T : Config + { + return 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( $"Exception while creating config {t.ToString()}, Msg {e.Message}" ); + } + + //cfg.SetFilename( filename ); + + if( s_cfg.writeOutTemplateFiles ) + { + var templateFile = $"templates/{filename}"; + + var dirName = Path.GetDirectoryName( templateFile ); + + lib.Util.checkAndAddDirectory( dirName ); + + lib.Log.info( $"Writing out template config of type {t.Name} in {templateFile}" ); + + Config.save( cfg, templateFile ); + } + } + + 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/Imm.cs b/imm/Imm.cs similarity index 94% rename from Imm.cs rename to imm/Imm.cs index fe30cef..42522bb 100644 --- a/Imm.cs +++ b/imm/Imm.cs @@ -1,15 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -// A spot for immutable helpers - -public static class imm -{ - - -} +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +// A spot for immutable helpers + +public static class imm +{ + + +} diff --git a/Log.cs b/logging/Log.cs similarity index 100% rename from Log.cs rename to logging/Log.cs diff --git a/Pos.cs b/math/Pos.cs similarity index 95% rename from Pos.cs rename to math/Pos.cs index a97c97d..a90e61c 100644 --- a/Pos.cs +++ b/math/Pos.cs @@ -1,52 +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; - } +{ + + [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/Conn.cs b/net/Conn.cs similarity index 94% rename from Conn.cs rename to net/Conn.cs index 442dac0..2ce1f84 100644 --- a/Conn.cs +++ b/net/Conn.cs @@ -1,110 +1,110 @@ -using System; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; -using System.Net.Sockets; -using System.IO; - -//using Util; - -namespace lib -{ - - - - - public interface IProcess - { - void process( object obj ); - } - - - - - public class Conn - { - public Socket Sock { get { return m_socket; } } - public Stream Stream { get { return m_streamNet; } } - - - public Conn( Socket sock, IProcess proc ) - { - m_socket = sock; - - sock.NoDelay = true; - - m_streamNet = new NetworkStream( m_socket ); - - m_proc = proc; - } - - public object recieveObject() - { - return recieveObject( Stream ); - } - - public object recieveObject( Stream stream ) - { - object obj = null; - - var formatter = new XmlFormatter2(); - - try - { - obj = formatter.Deserialize( stream ); - } - catch( System.Xml.XmlException ex ) - { - lib.Log.error( $"Outer Exception {ex.Message}" ); - } - - return obj; - } - - public void send( object obj ) - { - - var formatter = new XmlFormatter2(); - - try - { - var ms = new MemoryStream( 1024 ); - formatter.Serialize( ms, obj ); - - //var str = System.Text.Encoding.Default.GetString( mm_buffer, 0, (int)ms.Position ); - //lib.Log.info( $"Sent data {str} of length {ms.Position}" ); - //lib.Log.info( $"Sent {obj}" ); - - 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 ) - { - lib.Log.warn( $"Exception sending obj {obj} of {e}" ); - throw; - } - } - - public virtual void recieve( object obj ) - { - if( m_proc != null ) - m_proc.process( obj ); - } - - Socket m_socket; - - NetworkStream m_streamNet; - - IProcess m_proc; - - - - //private BufferedStream m_streamBufIn; - //private BufferedStream m_streamBufOut; - } - - - -} +using System; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Net.Sockets; +using System.IO; + +//using Util; + +namespace lib +{ + + + + + public interface IProcess + { + void process( object obj ); + } + + + + + public class Conn + { + public Socket Sock { get { return m_socket; } } + public Stream Stream { get { return m_streamNet; } } + + + public Conn( Socket sock, IProcess proc ) + { + m_socket = sock; + + sock.NoDelay = true; + + m_streamNet = new NetworkStream( m_socket ); + + m_proc = proc; + } + + public object recieveObject() + { + return recieveObject( Stream ); + } + + public object recieveObject( Stream stream ) + { + object obj = null; + + var formatter = new XmlFormatter2(); + + try + { + obj = formatter.Deserialize( stream ); + } + catch( System.Xml.XmlException ex ) + { + lib.Log.error( $"Outer Exception {ex.Message}" ); + } + + return obj; + } + + public void send( object obj ) + { + + var formatter = new XmlFormatter2(); + + try + { + var ms = new MemoryStream( 1024 ); + formatter.Serialize( ms, obj ); + + //var str = System.Text.Encoding.Default.GetString( mm_buffer, 0, (int)ms.Position ); + //lib.Log.info( $"Sent data {str} of length {ms.Position}" ); + //lib.Log.info( $"Sent {obj}" ); + + 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 ) + { + lib.Log.warn( $"Exception sending obj {obj} of {e}" ); + throw; + } + } + + public virtual void recieve( object obj ) + { + if( m_proc != null ) + m_proc.process( obj ); + } + + Socket m_socket; + + NetworkStream m_streamNet; + + IProcess m_proc; + + + + //private BufferedStream m_streamBufIn; + //private BufferedStream m_streamBufOut; + } + + + +} diff --git a/NetMsg.cs b/net/NetMsg.cs similarity index 97% rename from NetMsg.cs rename to net/NetMsg.cs index 5e77ecb..cb67582 100644 --- a/NetMsg.cs +++ b/net/NetMsg.cs @@ -17,8 +17,8 @@ namespace lib.Net { m_username = name; m_password = pass; - } - + } + public readonly String m_username; public readonly String m_password; } @@ -29,23 +29,23 @@ namespace lib.Net 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. + //Subclasses of this need to be on an admin client. [Serializable] public class Admin - { - + { + }; [Serializable] public class CreateEntity : Admin - { - + { + } @@ -53,17 +53,17 @@ namespace lib.Net public class MoveEntity : Admin { - } + } #endregion - + [Serializable] public class EntityBase { public EntityBase( int id ) { m_id = id; - } - + } + public readonly int m_id; }; @@ -77,8 +77,8 @@ namespace lib.Net m_x = x; m_y = y; m_z = z; - } - + } + public readonly float m_x; public readonly float m_y; public readonly float m_z; @@ -90,14 +90,14 @@ namespace lib.Net public EntityDesc( int id ) : base( id ) { - } - - //Should an entity have a mesh? Be made up of multiple meshes? - public readonly String m_mesh; - } - - - - - + } + + //Should an entity have a mesh? Be made up of multiple meshes? + public readonly String m_mesh; + } + + + + + } diff --git a/Scr.cs b/reflect/Scr.cs similarity index 95% rename from Scr.cs rename to reflect/Scr.cs index c526320..3adcab3 100644 --- a/Scr.cs +++ b/reflect/Scr.cs @@ -1,220 +1,220 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - - - - - - - - -static public class scr -{ - - public class PredEnumerator - { - public static PredEnumerator Create( IEnumerator en, Predicate pred ) - { - return new PredEnumerator( en, pred ); - } - - public static PredEnumerator Create( IEnumerable en, Predicate pred ) - { - return new PredEnumerator( en.GetEnumerator(), pred ); - } - } - - public class PredEnumerator : PredEnumerator, IEnumerator - { - - public T Current => m_en.Current; - - object IEnumerator.Current => m_en.Current; - - public PredEnumerator( IEnumerator en, Predicate pred ) - { - m_en = en; - m_pred = pred; - } - - - public bool MoveNext() - { - var success = m_en.MoveNext(); - - if( !success ) - return false; - - while( !m_pred( m_en.Current ) && ( success = m_en.MoveNext() ) ) - { - - } - - return success; - } - - public void Reset() - { - m_en.Reset(); - } - - #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls - - protected virtual void Dispose( bool disposing ) - { - if( !disposedValue ) - { - if( disposing ) - { - // TODO: dispose managed state (managed objects). - } - - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. - - disposedValue = true; - } - } - - // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. - // ~MyEnumerator() - // { - // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - // Dispose(false); - // } - - // This code added to correctly implement the disposable pattern. - public void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose( true ); - // TODO: uncomment the following line if the finalizer is overridden above. - // GC.SuppressFinalize(this); - } - #endregion - - IEnumerator m_en; - Predicate m_pred; - } - - - public class PredEnumerable : IEnumerable - { - public PredEnumerable( PredEnumerator en ) - { - m_en = en; - } - - public IEnumerator GetEnumerator() - { - return m_en; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return m_en; - } - - PredEnumerator m_en; - } - - - public static void GetAllFields( Type t, List list ) - { - var fieldArr = t.GetFields( - BindingFlags.DeclaredOnly | - BindingFlags.NonPublic | - BindingFlags.Public | - BindingFlags.Instance); - - var en = PredEnumerator.Create( fieldArr.AsEnumerable(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null ); - - list.AddRange( new PredEnumerable( en ) ); - - if( t.BaseType != null && t.BaseType != typeof( object ) ) - { - GetAllFields( t.BaseType, list ); - } - } - - - public static ImmutableList GetAllFields( Type t ) - { - if( s_fieldCache.TryGetValue( t, out var info ) ) - return info; - - var list = new List(); - - GetAllFields( t, list ); - - var immList = list.ToImmutableList(); - - s_fieldCache = s_fieldCache.Add( t, immList ); - - return immList; - } - - - public static void GetAllProperties( Type t, List list ) - { - var propArr = t.GetProperties( - BindingFlags.DeclaredOnly | - BindingFlags.NonPublic | - BindingFlags.Public | - BindingFlags.Instance - ); - - - - var en = PredEnumerator.Create( propArr.AsEnumerable(), - fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null && !list.Exists( f => f.Name == fa.Name ) ); - - list.AddRange( new PredEnumerable( en ) ); - - if( t.BaseType != null && t.BaseType != typeof( object ) ) - { - GetAllProperties( t.BaseType, list ); - } - } - - public static ImmutableList GetAllProperties( Type t ) - { - if( s_propCache.TryGetValue( t, out var info ) ) - return info; - - var list = new List(); - - GetAllProperties( t, list ); - - var immList = list.ToImmutableList(); - - s_propCache = s_propCache.Add( t, immList ); - - return immList; - } - - - static ImmutableDictionary> s_fieldCache = ImmutableDictionary>.Empty; - static ImmutableDictionary> s_propCache = ImmutableDictionary>.Empty; - - - - - //SLOW - static public string TypeToIdentifier( string typename ) - { - return typename.Replace( '<', '_' ).Replace( '>', '_' ).Replace( ',', '_' ).Replace( ' ', '_' ).Replace( '.', '_' ).Replace( '+', '_' ).Replace( '[', '_' ).Replace( ']', '_' ).Replace( '$', '_' ).Replace( ':', '_' ); - } - - - - - -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + + + + + + + + +static public class scr +{ + + public class PredEnumerator + { + public static PredEnumerator Create( IEnumerator en, Predicate pred ) + { + return new PredEnumerator( en, pred ); + } + + public static PredEnumerator Create( IEnumerable en, Predicate pred ) + { + return new PredEnumerator( en.GetEnumerator(), pred ); + } + } + + public class PredEnumerator : PredEnumerator, IEnumerator + { + + public T Current => m_en.Current; + + object IEnumerator.Current => m_en.Current; + + public PredEnumerator( IEnumerator en, Predicate pred ) + { + m_en = en; + m_pred = pred; + } + + + public bool MoveNext() + { + var success = m_en.MoveNext(); + + if( !success ) + return false; + + while( !m_pred( m_en.Current ) && ( success = m_en.MoveNext() ) ) + { + + } + + return success; + } + + public void Reset() + { + m_en.Reset(); + } + + #region IDisposable Support + private bool disposedValue = false; // To detect redundant calls + + protected virtual void Dispose( bool disposing ) + { + if( !disposedValue ) + { + if( disposing ) + { + // TODO: dispose managed state (managed objects). + } + + // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. + // TODO: set large fields to null. + + disposedValue = true; + } + } + + // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. + // ~MyEnumerator() + // { + // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + // Dispose(false); + // } + + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose( true ); + // TODO: uncomment the following line if the finalizer is overridden above. + // GC.SuppressFinalize(this); + } + #endregion + + IEnumerator m_en; + Predicate m_pred; + } + + + public class PredEnumerable : IEnumerable + { + public PredEnumerable( PredEnumerator en ) + { + m_en = en; + } + + public IEnumerator GetEnumerator() + { + return m_en; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return m_en; + } + + PredEnumerator m_en; + } + + + public static void GetAllFields( Type t, List list ) + { + var fieldArr = t.GetFields( + BindingFlags.DeclaredOnly | + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Instance); + + var en = PredEnumerator.Create( fieldArr.AsEnumerable(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null ); + + list.AddRange( new PredEnumerable( en ) ); + + if( t.BaseType != null && t.BaseType != typeof( object ) ) + { + GetAllFields( t.BaseType, list ); + } + } + + + public static ImmutableList GetAllFields( Type t ) + { + if( s_fieldCache.TryGetValue( t, out var info ) ) + return info; + + var list = new List(); + + GetAllFields( t, list ); + + var immList = list.ToImmutableList(); + + s_fieldCache = s_fieldCache.Add( t, immList ); + + return immList; + } + + + public static void GetAllProperties( Type t, List list ) + { + var propArr = t.GetProperties( + BindingFlags.DeclaredOnly | + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Instance + ); + + + + var en = PredEnumerator.Create( propArr.AsEnumerable(), + fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null && !list.Exists( f => f.Name == fa.Name ) ); + + list.AddRange( new PredEnumerable( en ) ); + + if( t.BaseType != null && t.BaseType != typeof( object ) ) + { + GetAllProperties( t.BaseType, list ); + } + } + + public static ImmutableList GetAllProperties( Type t ) + { + if( s_propCache.TryGetValue( t, out var info ) ) + return info; + + var list = new List(); + + GetAllProperties( t, list ); + + var immList = list.ToImmutableList(); + + s_propCache = s_propCache.Add( t, immList ); + + return immList; + } + + + static ImmutableDictionary> s_fieldCache = ImmutableDictionary>.Empty; + static ImmutableDictionary> s_propCache = ImmutableDictionary>.Empty; + + + + + //SLOW + static public string TypeToIdentifier( string typename ) + { + return typename.Replace( '<', '_' ).Replace( '>', '_' ).Replace( ',', '_' ).Replace( ' ', '_' ).Replace( '.', '_' ).Replace( '+', '_' ).Replace( '[', '_' ).Replace( ']', '_' ).Replace( '$', '_' ).Replace( ':', '_' ); + } + + + + + +} diff --git a/SerializableDictionary.cs b/ser/SerializableDictionary.cs similarity index 96% rename from SerializableDictionary.cs rename to ser/SerializableDictionary.cs index 229453d..8873863 100644 --- a/SerializableDictionary.cs +++ b/ser/SerializableDictionary.cs @@ -9,157 +9,157 @@ using System.IO; using System.Security.Permissions; namespace lib -{ - [Serializable] - public class SerializableDictionary : Dictionary, IXmlSerializable, ISerializable - { +{ + [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"; + 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 ) - { - } - + 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{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{itemIdx}" ), kvp, typeof( KeyValuePair ) ); - itemIdx++; - } - } - + + 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{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{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; - } - + + 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; - } - } + 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; + private XmlSerializer keySerializer = null; + private XmlSerializer valueSerializer = null; #endregion } } diff --git a/VersionFormatter.cs b/ser/VersionFormatter.cs similarity index 94% rename from VersionFormatter.cs rename to ser/VersionFormatter.cs index 85883fd..bde4613 100644 --- a/VersionFormatter.cs +++ b/ser/VersionFormatter.cs @@ -1,677 +1,677 @@ -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 < length; ++i ) - { - int val = reader.ReadInt32(); - - //m_fixups[ val ] = new Fixup( obj, fi ); - - if( fi != null ) - { - m_fixupList.Add( new Fixup( val, array, i ) ); - } - } - } - - void readRef( BinaryReader reader, object obj, FieldInfo fi ) - { - int val = reader.ReadInt32(); - - //m_fixups[ val ] = new Fixup( obj, fi ); - - m_fixupList.Add( new Fixup( val, obj, fi ) ); - } - - void readInt( BinaryReader reader, object obj, FieldInfo fi ) - { - int val = reader.ReadInt32(); - - if( fi == null ) - return; - - if( !fi.FieldType.IsEnum ) - { - fi.SetValue( obj, val ); - } - else - { - object enumVal = Enum.Parse( fi.FieldType, val.ToString() ); - fi.SetValue( obj, Convert.ChangeType( enumVal, fi.FieldType ) ); - } - - } - - void readSingle( BinaryReader reader, object obj, FieldInfo fi ) - { - float val = reader.ReadSingle(); - - if( fi == null ) - return; - - fi.SetValue( obj, val ); - } - - void readDouble( BinaryReader reader, object obj, FieldInfo fi ) - { - double val = reader.ReadDouble(); - - if( fi == null ) - return; - - fi.SetValue( obj, val ); - } - - void readChar( BinaryReader reader, object obj, FieldInfo fi ) - { - char val = reader.ReadChar(); - - if( fi == null ) - return; - - fi.SetValue( obj, val ); - } - - void readString( BinaryReader reader, object obj, FieldInfo fi ) - { - string val = reader.ReadString(); - - if( fi == null ) - return; - - fi.SetValue( obj, val ); - } - - void readBool( BinaryReader reader, object obj, FieldInfo fi ) - { - bool val = reader.ReadBoolean(); - - if( fi == null ) - return; - - fi.SetValue( obj, val ); - } - - #endregion Deserialize - - - } -} - - - - - - - - - - - - - - - - - - - +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 < length; ++i ) + { + int val = reader.ReadInt32(); + + //m_fixups[ val ] = new Fixup( obj, fi ); + + if( fi != null ) + { + m_fixupList.Add( new Fixup( val, array, i ) ); + } + } + } + + void readRef( BinaryReader reader, object obj, FieldInfo fi ) + { + int val = reader.ReadInt32(); + + //m_fixups[ val ] = new Fixup( obj, fi ); + + m_fixupList.Add( new Fixup( val, obj, fi ) ); + } + + void readInt( BinaryReader reader, object obj, FieldInfo fi ) + { + int val = reader.ReadInt32(); + + if( fi == null ) + return; + + if( !fi.FieldType.IsEnum ) + { + fi.SetValue( obj, val ); + } + else + { + object enumVal = Enum.Parse( fi.FieldType, val.ToString() ); + fi.SetValue( obj, Convert.ChangeType( enumVal, fi.FieldType ) ); + } + + } + + void readSingle( BinaryReader reader, object obj, FieldInfo fi ) + { + float val = reader.ReadSingle(); + + if( fi == null ) + return; + + fi.SetValue( obj, val ); + } + + void readDouble( BinaryReader reader, object obj, FieldInfo fi ) + { + double val = reader.ReadDouble(); + + if( fi == null ) + return; + + fi.SetValue( obj, val ); + } + + void readChar( BinaryReader reader, object obj, FieldInfo fi ) + { + char val = reader.ReadChar(); + + if( fi == null ) + return; + + fi.SetValue( obj, val ); + } + + void readString( BinaryReader reader, object obj, FieldInfo fi ) + { + string val = reader.ReadString(); + + if( fi == null ) + return; + + fi.SetValue( obj, val ); + } + + void readBool( BinaryReader reader, object obj, FieldInfo fi ) + { + bool val = reader.ReadBoolean(); + + if( fi == null ) + return; + + fi.SetValue( obj, val ); + } + + #endregion Deserialize + + + } +} + + + + + + + + + + + + + + + + + + + diff --git a/XmlFormatter.cs b/ser/XmlFormatter.cs similarity index 96% rename from XmlFormatter.cs rename to ser/XmlFormatter.cs index 371b8ca..310b083 100644 --- a/XmlFormatter.cs +++ b/ser/XmlFormatter.cs @@ -7,28 +7,28 @@ using System.Collections; using System.Collections.Generic; -using System.Reflection; -//using System.Collections; -//using System.Diagnostics; -//using System.Globalization; -//using System.ComponentModel; - - +using System.Reflection; +//using System.Collections; +//using System.Diagnostics; +//using System.Globalization; +//using System.ComponentModel; + + namespace lib -{ - //Old, use 2 now. +{ + //Old, use 2 now. class XmlFormatter : IFormatter { StreamingContext m_context; - //SerializationMode m_mode; - //KnownTypeCollection known_types; - //IDataContractSurrogate m_surrogate; - //int m_maxItems; - + //SerializationMode m_mode; + //KnownTypeCollection known_types; + //IDataContractSurrogate m_surrogate; + //int m_maxItems; + public XmlFormatter() { } - + /* public XmlFormatter( SerializationMode mode ) { @@ -45,33 +45,33 @@ namespace lib { m_mode = mode; m_context = context; - } - */ - - //public XmlFormatter (SerializationMode mode, - // StreamingContext context, KnownTypeCollection knownTypes) - //{ - //} - - SerializationBinder IFormatter.Binder + } + */ + + //public XmlFormatter (SerializationMode mode, + // StreamingContext context, KnownTypeCollection knownTypes) + //{ + //} + + SerializationBinder IFormatter.Binder { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } - ISurrogateSelector IFormatter.SurrogateSelector + ISurrogateSelector IFormatter.SurrogateSelector { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } - public StreamingContext Context + public StreamingContext Context { get { return m_context; } set { m_context = value; } } - + /* public KnownTypeCollection KnownTypes { get { return known_types; } @@ -81,8 +81,8 @@ namespace lib get { return m_maxItems; } set { m_maxItems= value; } } - */ - + */ + object IFormatter.Deserialize( Stream stream ) { @@ -142,9 +142,9 @@ namespace lib MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type ); - object obj = Activator.CreateInstance( type ); - - + object obj = Activator.CreateInstance( type ); + + /* object obj = FormatterServices.GetUninitializedObject( type ); @@ -157,8 +157,8 @@ namespace lib return null; obj = ci.Invoke( null ); - */ - + */ + for( int i = 0; i < miArr.Length; ++i ) { FieldInfo fi = (FieldInfo)miArr[ i ]; @@ -198,9 +198,9 @@ namespace lib } } else - { - //FormatterServices.GetUninitializedObject() - + { + //FormatterServices.GetUninitializedObject() + int length = s_conv.ToInt32( child.GetAttribute( "c" ) ); string elemType = child.GetAttribute( "t" ); @@ -223,28 +223,28 @@ namespace lib else { if( nodeList.Count == 0 ) - { - // Should be - - //object obj2 = fi.GetRawConstantValue(); + { + // Should be + + //object obj2 = fi.GetRawConstantValue(); } - else //More than 1. - { - //Log.error( "Too many fields named the same thing" ); + 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 ); - + } + + //FieldInfo fi = (FieldInfo)miArr[0]; + + //ConstructorInfo ci = fi.FieldType.TypeInitializer; + + //ci.Invoke( null ); + return obj; - } - - + } + + /* public T Deserialize (Stream stream) { @@ -260,18 +260,18 @@ namespace lib { 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; @@ -291,10 +291,10 @@ namespace lib bool writeContentOnly, bool ignoreUnknownSerializationData ) { - Type t = graph.GetType(); - - //writer.WriteStartDocument(); - + Type t = graph.GetType(); + + //writer.WriteStartDocument(); + if( Type.GetTypeCode( t ) == TypeCode.Object ) { writer.WriteStartElement( "root" ); @@ -309,8 +309,8 @@ namespace lib foreach( FieldInfo fi in fiArr ) { - Serialize( writer, fi.Name, fi.GetValue( graph ) ); - + Serialize( writer, fi.Name, fi.GetValue( graph ) ); + /* if( fi.FieldType.IsClass ) { @@ -320,13 +320,13 @@ namespace lib { SerializePod( writer, fi.GetValue( graph ) ); } - */ + */ } writer.WriteEndElement(); - } - - //writer.WriteEndDocument(); + } + + //writer.WriteEndDocument(); } private ObjectIDGenerator m_idGenerator = new ObjectIDGenerator(); @@ -379,14 +379,14 @@ namespace lib for( int i = 0; i < arr.Length; ++i ) { Serialize( writer, "val", arr.GetValue( i ) ); - } - - //writer.WriteStartElement( "values" ); - - - - //writer.WriteEndElement(); - + } + + //writer.WriteStartElement( "values" ); + + + + //writer.WriteEndElement(); + } } else @@ -410,685 +410,685 @@ namespace lib } } -} - - - - - - - - - - - - - - - - - - -/* -/// -/// -/// -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 +/// +/// +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 ) - { - 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 Type[] mm_consType = new Type[ 2 ]; - private object[] mm_args = new object[ 2 ]; - 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( finalType, new FormatterConverter() ); - - //var serInfoForTypes = new SerializationInfo( type, new FormatterConverter() ); - - //ser.GetObjectData( serInfoForTypes, Context ); - - foreach( var objNode in allChildren ) - { - var node = objNode as XmlElement; - - String name = node.Name; - - String childType = node.GetAttribute( "t" ); - - name = scr.TypeToIdentifier( name ); - - XmlElement childElem = getNamedChild( allChildren, name ); - - var des = Deserialize( childElem, childType ); - - serInfo.AddValue( name, des, des.GetType() ); - } - - //ConstructorInfo[] allCons = obj.GetType().GetConstructors( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); - - //var serMem = FormatterServices.GetSerializableMembers( finalType ); - - //object objUn = FormatterServices.GetSafeUninitializedObject( finalType ); - - IDeserializationCallback objUnOnDeser = obj as IDeserializationCallback; - - mm_consType[0] = typeof( SerializationInfo ); - mm_consType[1] = typeof( StreamingContext ); - ConstructorInfo serCons = finalType.GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, mm_consType, null ); - - mm_args[0] = serInfo; - mm_args[1] = Context; - serCons.Invoke( obj, mm_args ); - - if( objUnOnDeser != null ) - { - objUnOnDeser.OnDeserialization( objUnOnDeser ); - } - - /* - ser.GetObjectData( serInfo, Context ); - - //var serEnum = ; - - foreach( var serMember in serInfo ) - { - String name = serMember.Name; - - name = scr.TypeToIdentifier( name ); - - XmlElement childElem = getNamedChild( allChildren, name ); - - var des = Deserialize( childElem, name ); - } - */ - } - else - { - XmlNodeList allChildren = elem.ChildNodes; - - var fields = scr.GetAllFields( type ); - - //MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type, Context ); - - foreach( var childFi in fields ) - { - - String name = childFi.Name; - - name = scr.TypeToIdentifier( name ); - - XmlElement childElem = getNamedChild( allChildren, name ); - - - if( childElem != null ) - { - object childObj = Deserialize( childElem, childFi.FieldType, obj ); - - childFi.SetValue( obj, childObj ); - } - else if( fields.Count == 1 ) - { - object childObj = Deserialize( elem, 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( m_cfg.datastructure == Datastructure.Full && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) - { - //lib.log.info( "Reusing object for {0}", refInt ); - return m_alreadySerialized[refInt]; - } - else - { - object obj = null; - - try - { - //Trying the nice way to creat objects first. - obj = Activator.CreateInstance( type ); - - } - catch( Exception ) - { - try - { - obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type ); - } - catch( Exception exInner ) - { - lib.Log.error( $"Got exception {exInner.Message} trying to make an uninitialized object" ); - } - - } - - if( obj == null ) - { - lib.Log.warn( $"Could not create object of type {type.Name}" ); - - return obj; - } - - if( m_cfg.datastructure == Datastructure.Full && 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( m_cfg.datastructure == Datastructure.Full && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) - { - return (Array)m_alreadySerialized[refInt]; - } - else - { - Array arr = Array.CreateInstance( elemType, length ) ; - - if( m_cfg.datastructure == Datastructure.Full ) - { - 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", true ); - //writer.WriteEndDocument(); - } - - private void Serialize( XmlWriter writer, object root, string name, bool forceType ) - { - writer.WriteStartElement( name ); - - if( root != null ) - { - Type type = root.GetType(); - - TypeCode typeCode = Type.GetTypeCode( type ); - - if( typeCode != TypeCode.Object ) - { - SerializeConcrete( writer, root, forceType ); - } - 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, bool forceType ) - { - //TODO: Only write this out if debugging. - if( forceType ) - { - 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 ); - - if( m_cfg.datastructure == Datastructure.Full ) - { - writer.WriteAttributeString( "ref", refInt.ToString() ); - - } - - if( first ) - { - if( m_cfg.datastructure == Datastructure.Full ) - { - 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 = scr.TypeToIdentifier( name ); - - Serialize( writer, serMember.Value, name, true ); - } - - //var sc = new SerializationContext( - - //ser.GetObjectData( - } - else - //*/ - { - var fields = scr.GetAllFields( type ); - - //MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type, Context ); - - foreach( var childFi in fields ) - { - - object[] objs = childFi.GetCustomAttributes( typeof( NonSerializedAttribute ), true ); - - if( objs.Length > 0 ) - { - continue; - } - - String name = childFi.Name; - - name = scr.TypeToIdentifier( name ); - - Serialize( writer, childFi.GetValue( root ), name, false ); - } - } - } - } - - private void SerializeArray( XmlWriter writer, object root ) - { - Array arr = (Array)root; - - Type typeElem = arr.GetType().GetElementType(); - - Type type = root.GetType(); - - writer.WriteAttributeString( "t", getTypeName( type ) ); - - bool first; - - long refInt = m_objectID.GetId( root, out first ); - - if( m_cfg.datastructure == Datastructure.Full ) - { - writer.WriteAttributeString( "ref", refInt.ToString() ); - } - - if( first ) - { - if( m_cfg.datastructure == Datastructure.Full ) - { - m_alreadySerialized[refInt] = root; - } - - - for( int i = 0; i < arr.Length; ++i ) - { - Serialize( writer, arr.GetValue( i ), "i" + i.ToString(), false ); - } - } - } - #endregion - } - -} +using System; +using System.IO; +using System.Xml; +using System.Runtime.Serialization; +//using System.Web.Configuration; +using System.Collections; +using System.Collections.Generic; + + +using System.Reflection; +using System.Diagnostics; + +using System.Runtime.InteropServices; + +namespace lib +{ + + public interface I_Serialize + { + void OnSerialize(); + void OnDeserialize( object enclosing ); + } + + public enum Datastructure + { + Invalid, + Tree, + Full, + + } + + public class XmlFormatter2Cfg : Config + { + public readonly Datastructure datastructure = Datastructure.Full; + } + + public class XmlFormatter2 : IFormatter + { + public StreamingContext Context { get; set; } + + static Random s_rnd = new Random(); + int m_rndVal = s_rnd.Next(); + + XmlFormatter2Cfg m_cfg = new XmlFormatter2Cfg(); + + + + #region Unimplimented + public ISurrogateSelector SurrogateSelector + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public SerializationBinder Binder + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + #endregion + + + + + + + public XmlFormatter2() + { + Context = new StreamingContext( StreamingContextStates.All ); + } + + + + + public XmlFormatter2( XmlFormatter2Cfg cfg ) + { + Context = new StreamingContext( StreamingContextStates.All ); + + m_cfg = cfg; + } + + + + #region Deserialize + private static FormatterConverter s_conv = new FormatterConverter(); + + public object Deserialize( Stream stream ) + { + //lib.log.info( "Deserialize( Stream stream ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + return DeserializeKnownType( stream, null ); + //lib.log.info( "Deserialize END ( Stream stream ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + } + + public object DeserializeKnownType( Stream stream, Type t ) + { + //lib.log.info( "DeserializeKnownType( Stream stream, Type t ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + + XmlTextReader reader = new XmlTextReader( stream ); + //reader.Settings = System.Text.Encoding.ASCII; + + object obj = Deserialize( reader, t ); + //lib.log.info( "DeserializeKnownType END( Stream stream, Type t ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + return obj; + } + + private object Deserialize( XmlReader reader, Type t ) + { + //lib.log.info( "Deserialize( XmlReader reader, Type t ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + + m_alreadySerialized.Clear(); + m_objectID = new ObjectIDGenerator(); + + reader.Read(); + + XmlDocument doc = new XmlDocument(); + + doc.Load( reader ); + + ////lib.log.info( "What to deserialize {0}", doc.OuterXml.ToString() ); + + if( t == null ) + return Deserialize( doc.DocumentElement ); + + return Deserialize( doc.DocumentElement, t ); + } + + private object Deserialize( XmlElement elem ) + { + //lib.log.info( "object Deserialize( XmlElement elem ) {0} {1}", m_rndVal, m_alreadySerialized.Count ); + + string typename = elem.HasAttribute( "t" ) ? elem.GetAttribute( "t" ) : elem.Name; + + return Deserialize( elem, typename ); + } + + private object Deserialize( XmlElement elem, string typename ) + { + AppDomain currentDomain = AppDomain.CurrentDomain; + Assembly[] assems = currentDomain.GetAssemblies(); + + Type type = null; + + // @@@@: This should go backwards, we tend to lookup our own stuff, then builtins. + // Also, cache a typename into its assembly. + foreach( Assembly a in assems ) + { + type = a.GetType( typename ); + + if( type != null ) + break; + } + + if( type == null ) + { + return null; + } + + return Deserialize( elem, type ); + } + + private object Deserialize( XmlElement elem, Type type, object enclosing = null ) + { + TypeCode typeCode = Type.GetTypeCode( type ); + + if( typeCode != TypeCode.Object ) + { + return DeserializeConcrete( elem, type ); + } + else + { + if( !type.IsArray ) + { + object obj = DeserializeObject( elem, type ); + + if( obj is I_Serialize ) + { + var iser = obj as I_Serialize; + + iser.OnDeserialize( enclosing ); + } + + return obj; + } + else + { + return DeserializeArray( elem, type ); + } + } + } + + Type[] mm_types = new Type[1]; + private object GetDefault( Type t ) + { + mm_types[0] = t; + + var fn = GetType().GetMethod( "GetDefaultGeneric" ).MakeGenericMethod( mm_types ); + + return fn.Invoke( this, null ); + } + + public T GetDefaultGeneric() + { + 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 ) + { + 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 Type[] mm_consType = new Type[ 2 ]; + private object[] mm_args = new object[ 2 ]; + 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( finalType, new FormatterConverter() ); + + //var serInfoForTypes = new SerializationInfo( type, new FormatterConverter() ); + + //ser.GetObjectData( serInfoForTypes, Context ); + + foreach( var objNode in allChildren ) + { + var node = objNode as XmlElement; + + String name = node.Name; + + String childType = node.GetAttribute( "t" ); + + name = scr.TypeToIdentifier( name ); + + XmlElement childElem = getNamedChild( allChildren, name ); + + var des = Deserialize( childElem, childType ); + + serInfo.AddValue( name, des, des.GetType() ); + } + + //ConstructorInfo[] allCons = obj.GetType().GetConstructors( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + + //var serMem = FormatterServices.GetSerializableMembers( finalType ); + + //object objUn = FormatterServices.GetSafeUninitializedObject( finalType ); + + IDeserializationCallback objUnOnDeser = obj as IDeserializationCallback; + + mm_consType[0] = typeof( SerializationInfo ); + mm_consType[1] = typeof( StreamingContext ); + ConstructorInfo serCons = finalType.GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, mm_consType, null ); + + mm_args[0] = serInfo; + mm_args[1] = Context; + serCons.Invoke( obj, mm_args ); + + if( objUnOnDeser != null ) + { + objUnOnDeser.OnDeserialization( objUnOnDeser ); + } + + /* + ser.GetObjectData( serInfo, Context ); + + //var serEnum = ; + + foreach( var serMember in serInfo ) + { + String name = serMember.Name; + + name = scr.TypeToIdentifier( name ); + + XmlElement childElem = getNamedChild( allChildren, name ); + + var des = Deserialize( childElem, name ); + } + */ + } + else + { + XmlNodeList allChildren = elem.ChildNodes; + + var fields = scr.GetAllFields( type ); + + //MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type, Context ); + + foreach( var childFi in fields ) + { + + String name = childFi.Name; + + name = scr.TypeToIdentifier( name ); + + XmlElement childElem = getNamedChild( allChildren, name ); + + + if( childElem != null ) + { + object childObj = Deserialize( childElem, childFi.FieldType, obj ); + + childFi.SetValue( obj, childObj ); + } + else if( fields.Count == 1 ) + { + object childObj = Deserialize( elem, 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( m_cfg.datastructure == Datastructure.Full && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) + { + //lib.log.info( "Reusing object for {0}", refInt ); + return m_alreadySerialized[refInt]; + } + else + { + object obj = null; + + try + { + //Trying the nice way to creat objects first. + obj = Activator.CreateInstance( type ); + + } + catch( Exception ) + { + try + { + obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type ); + } + catch( Exception exInner ) + { + lib.Log.error( $"Got exception {exInner.Message} trying to make an uninitialized object" ); + } + + } + + if( obj == null ) + { + lib.Log.warn( $"Could not create object of type {type.Name}" ); + + return obj; + } + + if( m_cfg.datastructure == Datastructure.Full && 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( m_cfg.datastructure == Datastructure.Full && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) + { + return (Array)m_alreadySerialized[refInt]; + } + else + { + Array arr = Array.CreateInstance( elemType, length ) ; + + if( m_cfg.datastructure == Datastructure.Full ) + { + 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", true ); + //writer.WriteEndDocument(); + } + + private void Serialize( XmlWriter writer, object root, string name, bool forceType ) + { + writer.WriteStartElement( name ); + + if( root != null ) + { + Type type = root.GetType(); + + TypeCode typeCode = Type.GetTypeCode( type ); + + if( typeCode != TypeCode.Object ) + { + SerializeConcrete( writer, root, forceType ); + } + 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, bool forceType ) + { + //TODO: Only write this out if debugging. + if( forceType ) + { + 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 ); + + if( m_cfg.datastructure == Datastructure.Full ) + { + writer.WriteAttributeString( "ref", refInt.ToString() ); + + } + + if( first ) + { + if( m_cfg.datastructure == Datastructure.Full ) + { + 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 = scr.TypeToIdentifier( name ); + + Serialize( writer, serMember.Value, name, true ); + } + + //var sc = new SerializationContext( + + //ser.GetObjectData( + } + else + //*/ + { + var fields = scr.GetAllFields( type ); + + //MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type, Context ); + + foreach( var childFi in fields ) + { + + object[] objs = childFi.GetCustomAttributes( typeof( NonSerializedAttribute ), true ); + + if( objs.Length > 0 ) + { + continue; + } + + String name = childFi.Name; + + name = scr.TypeToIdentifier( name ); + + Serialize( writer, childFi.GetValue( root ), name, false ); + } + } + } + } + + private void SerializeArray( XmlWriter writer, object root ) + { + Array arr = (Array)root; + + Type typeElem = arr.GetType().GetElementType(); + + Type type = root.GetType(); + + writer.WriteAttributeString( "t", getTypeName( type ) ); + + bool first; + + long refInt = m_objectID.GetId( root, out first ); + + if( m_cfg.datastructure == Datastructure.Full ) + { + writer.WriteAttributeString( "ref", refInt.ToString() ); + } + + if( first ) + { + if( m_cfg.datastructure == Datastructure.Full ) + { + m_alreadySerialized[refInt] = root; + } + + + for( int i = 0; i < arr.Length; ++i ) + { + Serialize( writer, arr.GetValue( i ), "i" + i.ToString(), false ); + } + } + } + #endregion + } + +} diff --git a/Clock.cs b/time/Clock.cs similarity index 94% rename from Clock.cs rename to time/Clock.cs index 8ce82aa..caa86e8 100644 --- a/Clock.cs +++ b/time/Clock.cs @@ -1,52 +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; - - } -} +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/Timer.cs b/time/Timer.cs similarity index 95% rename from Timer.cs rename to time/Timer.cs index 0c6ee33..4f4cf73 100644 --- a/Timer.cs +++ b/time/Timer.cs @@ -1,377 +1,377 @@ -using System; -using System.Runtime.InteropServices; -using System.ComponentModel; -using System.Threading; - -namespace lib -{ - - public class MicroStopwatch : System.Diagnostics.Stopwatch - { - readonly double _microSecPerTick - = 1000000D / System.Diagnostics.Stopwatch.Frequency; - - public MicroStopwatch() - { - if( !System.Diagnostics.Stopwatch.IsHighResolution ) - { - throw new Exception( "On this system the high-resolution " + - "performance counter is not available" ); - } - } - - public long ElapsedMicroseconds - { - get - { - return (long)( ElapsedTicks * _microSecPerTick ); - } - } - } - - /// - /// MicroTimer class - /// - public class MicroTimer - { - public delegate void MicroTimerElapsedEventHandler( - object sender, - MicroTimerEventArgs timerEventArgs ); - public event MicroTimerElapsedEventHandler MicroTimerElapsed; - - System.Threading.Thread _threadTimer = null; - long _ignoreEventIfLateBy = long.MaxValue; - long _timerIntervalInMicroSec = 0; - bool _stopTimer = true; - - public MicroTimer() - { - } - - public MicroTimer( long timerIntervalInMicroseconds ) - { - Interval = timerIntervalInMicroseconds; - } - - public long Interval - { - get - { - return System.Threading.Interlocked.Read( - ref _timerIntervalInMicroSec ); - } - set - { - System.Threading.Interlocked.Exchange( - ref _timerIntervalInMicroSec, value ); - } - } - - public long IgnoreEventIfLateBy - { - get - { - return System.Threading.Interlocked.Read( - ref _ignoreEventIfLateBy ); - } - set - { - System.Threading.Interlocked.Exchange( - ref _ignoreEventIfLateBy, value <= 0 ? long.MaxValue : value ); - } - } - - public bool Enabled - { - set - { - if( value ) - { - Start(); - } - else - { - Stop(); - } - } - get - { - return ( _threadTimer != null && _threadTimer.IsAlive ); - } - } - - public void Start() - { - if( Enabled || Interval <= 0 ) - { - return; - } - - _stopTimer = false; - - System.Threading.ThreadStart threadStart = delegate() - { - NotificationTimer(ref _timerIntervalInMicroSec, - ref _ignoreEventIfLateBy, - ref _stopTimer); - }; - - _threadTimer = new System.Threading.Thread( threadStart ); - _threadTimer.Priority = System.Threading.ThreadPriority.Highest; - _threadTimer.Start(); - } - - public void Stop() - { - _stopTimer = true; - - if( _threadTimer != null && _threadTimer.ManagedThreadId == - System.Threading.Thread.CurrentThread.ManagedThreadId ) - { - return; - } - - while( Enabled ) - { - System.Threading.Thread.SpinWait( 10 ); - } - } - - void NotificationTimer( ref long timerIntervalInMicroSec, - ref long ignoreEventIfLateBy, - ref bool stopTimer ) - { - int timerCount = 0; - long nextNotification = 0; - - MicroStopwatch microStopwatch = new MicroStopwatch(); - microStopwatch.Start(); - - while( !stopTimer ) - { - long callbackFunctionExecutionTime = - microStopwatch.ElapsedMicroseconds - nextNotification; - - long timerIntervalInMicroSecCurrent = - System.Threading.Interlocked.Read(ref timerIntervalInMicroSec); - long ignoreEventIfLateByCurrent = - System.Threading.Interlocked.Read(ref ignoreEventIfLateBy); - - nextNotification += timerIntervalInMicroSecCurrent; - timerCount++; - long elapsedMicroseconds = 0; - - while( ( elapsedMicroseconds = microStopwatch.ElapsedMicroseconds ) - < nextNotification ) - { - System.Threading.Thread.SpinWait( 10 ); - } - - long timerLateBy = elapsedMicroseconds - nextNotification; - - if( timerLateBy >= ignoreEventIfLateByCurrent ) - { - continue; - } - - MicroTimerEventArgs microTimerEventArgs = - new MicroTimerEventArgs(timerCount, - elapsedMicroseconds, - timerLateBy, - callbackFunctionExecutionTime); - MicroTimerElapsed( this, microTimerEventArgs ); - } - - microStopwatch.Stop(); - } - } - - /// - /// MicroTimer Event Argument class - /// - public class MicroTimerEventArgs : EventArgs - { - // Simple counter, number times timed event (callback function) executed - public int TimerCount { get; private set; } - - // Time when timed event was called since timer started - public long ElapsedMicroseconds { get; private set; } - - // How late the timer was compared to when it should have been called - public long TimerLateBy { get; private set; } - - // Time it took to execute previous call to callback function (OnTimedEvent) - public long CallbackFunctionExecutionTime { get; private set; } - - public MicroTimerEventArgs( int timerCount, - long elapsedMicroseconds, - long timerLateBy, - long callbackFunctionExecutionTime ) - { - TimerCount = timerCount; - ElapsedMicroseconds = elapsedMicroseconds; - TimerLateBy = timerLateBy; - CallbackFunctionExecutionTime = callbackFunctionExecutionTime; - } - } - - - public class Timer - { - MicroStopwatch m_watch; - private long startTime; - private long stopTime; - private long freq; - private long freq_millis; - - public Timer() - { - m_watch = new MicroStopwatch(); - //startTime = m_watch.ElapsedMicroseconds; - //stopTime = m_watch.ElapsedMicroseconds; - freq = 1000 * 1000; - freq_millis = freq / 1000; - - Start(); - } - - // Start the timer - - public Timer Start() - { - m_watch.Start(); - startTime = m_watch.ElapsedMicroseconds; - stopTime = m_watch.ElapsedMicroseconds; - return this; - } - - // Stop the timer - - public Timer Stop() - { - m_watch.Stop(); - stopTime = m_watch.ElapsedMicroseconds; - return this; - } - - public double Seconds - { - get - { - long current = m_watch.ElapsedMicroseconds; - return (double)( current - startTime ) / freq; - } - } - - public long Current - { - get - { - long current = m_watch.ElapsedMicroseconds; - return ( current - startTime ) / freq_millis; - } - } - - public double Duration - { - get - { - return (double)( stopTime - startTime ) / (double)freq; - } - } - - public long DurationMS - { - get { return ( stopTime - startTime ) / freq_millis; } - } - } - - - public class TimerWin - { - [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 TimerWin() - { - 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; } - } - } -} +using System; +using System.Runtime.InteropServices; +using System.ComponentModel; +using System.Threading; + +namespace lib +{ + + public class MicroStopwatch : System.Diagnostics.Stopwatch + { + readonly double _microSecPerTick + = 1000000D / System.Diagnostics.Stopwatch.Frequency; + + public MicroStopwatch() + { + if( !System.Diagnostics.Stopwatch.IsHighResolution ) + { + throw new Exception( "On this system the high-resolution " + + "performance counter is not available" ); + } + } + + public long ElapsedMicroseconds + { + get + { + return (long)( ElapsedTicks * _microSecPerTick ); + } + } + } + + /// + /// MicroTimer class + /// + public class MicroTimer + { + public delegate void MicroTimerElapsedEventHandler( + object sender, + MicroTimerEventArgs timerEventArgs ); + public event MicroTimerElapsedEventHandler MicroTimerElapsed; + + System.Threading.Thread _threadTimer = null; + long _ignoreEventIfLateBy = long.MaxValue; + long _timerIntervalInMicroSec = 0; + bool _stopTimer = true; + + public MicroTimer() + { + } + + public MicroTimer( long timerIntervalInMicroseconds ) + { + Interval = timerIntervalInMicroseconds; + } + + public long Interval + { + get + { + return System.Threading.Interlocked.Read( + ref _timerIntervalInMicroSec ); + } + set + { + System.Threading.Interlocked.Exchange( + ref _timerIntervalInMicroSec, value ); + } + } + + public long IgnoreEventIfLateBy + { + get + { + return System.Threading.Interlocked.Read( + ref _ignoreEventIfLateBy ); + } + set + { + System.Threading.Interlocked.Exchange( + ref _ignoreEventIfLateBy, value <= 0 ? long.MaxValue : value ); + } + } + + public bool Enabled + { + set + { + if( value ) + { + Start(); + } + else + { + Stop(); + } + } + get + { + return ( _threadTimer != null && _threadTimer.IsAlive ); + } + } + + public void Start() + { + if( Enabled || Interval <= 0 ) + { + return; + } + + _stopTimer = false; + + System.Threading.ThreadStart threadStart = delegate() + { + NotificationTimer(ref _timerIntervalInMicroSec, + ref _ignoreEventIfLateBy, + ref _stopTimer); + }; + + _threadTimer = new System.Threading.Thread( threadStart ); + _threadTimer.Priority = System.Threading.ThreadPriority.Highest; + _threadTimer.Start(); + } + + public void Stop() + { + _stopTimer = true; + + if( _threadTimer != null && _threadTimer.ManagedThreadId == + System.Threading.Thread.CurrentThread.ManagedThreadId ) + { + return; + } + + while( Enabled ) + { + System.Threading.Thread.SpinWait( 10 ); + } + } + + void NotificationTimer( ref long timerIntervalInMicroSec, + ref long ignoreEventIfLateBy, + ref bool stopTimer ) + { + int timerCount = 0; + long nextNotification = 0; + + MicroStopwatch microStopwatch = new MicroStopwatch(); + microStopwatch.Start(); + + while( !stopTimer ) + { + long callbackFunctionExecutionTime = + microStopwatch.ElapsedMicroseconds - nextNotification; + + long timerIntervalInMicroSecCurrent = + System.Threading.Interlocked.Read(ref timerIntervalInMicroSec); + long ignoreEventIfLateByCurrent = + System.Threading.Interlocked.Read(ref ignoreEventIfLateBy); + + nextNotification += timerIntervalInMicroSecCurrent; + timerCount++; + long elapsedMicroseconds = 0; + + while( ( elapsedMicroseconds = microStopwatch.ElapsedMicroseconds ) + < nextNotification ) + { + System.Threading.Thread.SpinWait( 10 ); + } + + long timerLateBy = elapsedMicroseconds - nextNotification; + + if( timerLateBy >= ignoreEventIfLateByCurrent ) + { + continue; + } + + MicroTimerEventArgs microTimerEventArgs = + new MicroTimerEventArgs(timerCount, + elapsedMicroseconds, + timerLateBy, + callbackFunctionExecutionTime); + MicroTimerElapsed( this, microTimerEventArgs ); + } + + microStopwatch.Stop(); + } + } + + /// + /// MicroTimer Event Argument class + /// + public class MicroTimerEventArgs : EventArgs + { + // Simple counter, number times timed event (callback function) executed + public int TimerCount { get; private set; } + + // Time when timed event was called since timer started + public long ElapsedMicroseconds { get; private set; } + + // How late the timer was compared to when it should have been called + public long TimerLateBy { get; private set; } + + // Time it took to execute previous call to callback function (OnTimedEvent) + public long CallbackFunctionExecutionTime { get; private set; } + + public MicroTimerEventArgs( int timerCount, + long elapsedMicroseconds, + long timerLateBy, + long callbackFunctionExecutionTime ) + { + TimerCount = timerCount; + ElapsedMicroseconds = elapsedMicroseconds; + TimerLateBy = timerLateBy; + CallbackFunctionExecutionTime = callbackFunctionExecutionTime; + } + } + + + public class Timer + { + MicroStopwatch m_watch; + private long startTime; + private long stopTime; + private long freq; + private long freq_millis; + + public Timer() + { + m_watch = new MicroStopwatch(); + //startTime = m_watch.ElapsedMicroseconds; + //stopTime = m_watch.ElapsedMicroseconds; + freq = 1000 * 1000; + freq_millis = freq / 1000; + + Start(); + } + + // Start the timer + + public Timer Start() + { + m_watch.Start(); + startTime = m_watch.ElapsedMicroseconds; + stopTime = m_watch.ElapsedMicroseconds; + return this; + } + + // Stop the timer + + public Timer Stop() + { + m_watch.Stop(); + stopTime = m_watch.ElapsedMicroseconds; + return this; + } + + public double Seconds + { + get + { + long current = m_watch.ElapsedMicroseconds; + return (double)( current - startTime ) / freq; + } + } + + public long Current + { + get + { + long current = m_watch.ElapsedMicroseconds; + return ( current - startTime ) / freq_millis; + } + } + + public double Duration + { + get + { + return (double)( stopTime - startTime ) / (double)freq; + } + } + + public long DurationMS + { + get { return ( stopTime - startTime ) / freq_millis; } + } + } + + + public class TimerWin + { + [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 TimerWin() + { + 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; } + } + } +}