Better whitespace changes

This commit is contained in:
Marc Hernandez 2026-02-02 16:02:00 -08:00
parent 28d8c145b5
commit 6b1e193c90
14 changed files with 1415 additions and 1389 deletions

View File

@ -1,41 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net9.0;net10.0</TargetFrameworks>
<RootNamespace>lib</RootNamespace>
<AssemblyVersion>0.0.1.0</AssemblyVersion>
<FileVersion>0.0.1.0</FileVersion>
<Copyright>2003..2025 Marc Hernandez</Copyright>
<Description>A core set of libraries</Description>
<Platforms>AnyCPU;x64</Platforms>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>14.0</LangVersion>
<Copyright>Copyright 2003..2025 Marc Hernandez</Copyright>
<Description>A base set of </Description>
<PropertyGroup>
<TargetFrameworks>net9.0;net10.0</TargetFrameworks>
<RootNamespace>lib</RootNamespace>
<AssemblyVersion>0.0.1.0</AssemblyVersion>
<FileVersion>0.0.1.0</FileVersion>
<Copyright>2003..2025 Marc Hernandez</Copyright>
<Description>A core set of libraries</Description>
<Platforms>AnyCPU;x64</Platforms>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>14.0</LangVersion>
<Copyright>Copyright 2003..2025 Marc Hernandez</Copyright>
<Description>A base set of </Description>
<!--
I Want to turn this on, but cant yet. Implementing nullability 1 file at a gime
<Nullable>enable</Nullable>
-->
<NoWarn>$(NoWarn);SYSLIB0050;CS8981; CS8632</NoWarn>
</PropertyGroup>
<NoWarn>$(NoWarn);SYSLIB0050;CS8981; CS8632</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
<PackageReference Include="Optional" Version="4.0.0" />
<PackageReference Include="Optional.Async" Version="1.3.0" />
<PackageReference Include="System.Collections.Immutable" Version="9.0.9" />
<PackageReference Include="System.ValueTuple" Version="4.6.1" />
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
<PackageReference Include="Optional" Version="4.0.0" />
<PackageReference Include="Optional.Async" Version="1.3.0" />
<PackageReference Include="System.Collections.Immutable" Version="9.0.9" />
<PackageReference Include="System.ValueTuple" Version="4.6.1" />
<PackageReference Include="Microsoft.Diagnostics.NETCore.Client" Version="0.2.621003" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.24" />
<Folder Include="Properties\" />
<Folder Include="reflect\" />
<Folder Include="fsm\" />
<Folder Include="Properties\" />
<Folder Include="reflect\" />
<Folder Include="fsm\" />
<None Remove="fsm\" />
<None Remove="fsm\" />
</ItemGroup>
</ItemGroup>
</Project>

View File

@ -12,7 +12,7 @@ public abstract record class FsmContextBase<TSelf> : io.Recorded<TSelf>
where TSelf : FsmContextBase<TSelf>
{
// Required for 'with' expressions.
protected FsmContextBase(io.Recorded<TSelf> original) : base(original) { }
protected FsmContextBase( io.Recorded<TSelf> original ) : base( original ) { }
protected FsmContextBase() { }
}
@ -29,7 +29,7 @@ public abstract record class FsmStateBase<TSelf, TCtx> : io.Recorded<TSelf>
/// <summary>
/// Called when entering this state.
/// </summary>
public virtual (TCtx Context, TSelf State) OnEnter(TCtx context, FsmStateBase<TSelf, TCtx> oldState)
public virtual (TCtx Context, TSelf State) OnEnter( TCtx context, FsmStateBase<TSelf, TCtx> oldState )
{
return (context, (TSelf)this);
}
@ -37,13 +37,13 @@ public abstract record class FsmStateBase<TSelf, TCtx> : io.Recorded<TSelf>
/// <summary>
/// Called when exiting this state.
/// </summary>
public virtual (TCtx Context, TSelf State) OnExit(TCtx context, FsmStateBase<TSelf, TCtx> newState)
public virtual (TCtx Context, TSelf State) OnExit( TCtx context, FsmStateBase<TSelf, TCtx> newState )
{
return (context, (TSelf)this);
}
// Required for 'with' expressions.
protected FsmStateBase(io.Recorded<TSelf> original) : base(original) { }
protected FsmStateBase( io.Recorded<TSelf> original ) : base( original ) { }
protected FsmStateBase() { }
}
@ -62,14 +62,14 @@ public abstract record class FsmBase<TSelf, TState, TCtx> : io.Recorded<TSelf>
public TCtx Context { get; init; }
public TState State { get; init; }
protected FsmBase(TCtx initialContext, TState initialState)
protected FsmBase( TCtx initialContext, TState initialState )
{
Context = initialContext;
State = initialState;
}
// Required for 'with' expressions.
protected FsmBase(io.Recorded<TSelf> original) : base(original)
protected FsmBase( io.Recorded<TSelf> original ) : base( original )
{
var o = original as FsmBase<TSelf, TState, TCtx>;
Context = o!.Context;
@ -86,12 +86,12 @@ public abstract record class FsmBase<TSelf, TState, TCtx> : io.Recorded<TSelf>
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("newState")] string expression = "")
[CallerArgumentExpression( "newState" )] string expression = "" )
{
Console.WriteLine($"[FSM] Transition: {State.GetType().Name} -> {newState.GetType().Name}. Reason: {reason}");
Console.WriteLine( $"[FSM] Transition: {State.GetType().Name} -> {newState.GetType().Name}. Reason: {reason}" );
var (ctxAfterExit, stateAfterExit) = State.OnExit(Context, newState);
var (ctxAfterEnter, stateAfterEnter) = newState.OnEnter(ctxAfterExit, stateAfterExit);
var (ctxAfterExit, stateAfterExit) = State.OnExit( Context, newState );
var (ctxAfterEnter, stateAfterEnter) = newState.OnEnter( ctxAfterExit, stateAfterExit );
// Since 'this' is at least 'io.Recorded<TSelf>', we can call the
// detailed 'Process'. If 'this' is actually 'Timed<TSelf>', C#'s

View File

@ -9,43 +9,43 @@ using System.Runtime.CompilerServices;
/// </summary>
public static class imm
{
/// <summary>
/// Processes a 'Versioned' object (Level 1).
/// </summary>
public static T LightProcess<T>(
ref T obj,
Func<T, T> fn,
string reason = "Processed" )
where T : io.Versioned<T>
{
obj = obj.Process( fn, reason );
return obj;
}
/// <summary>
/// Processes a 'Recorded' object (Level 2), capturing caller info.
/// </summary>
public static T Process<T>(
ref T obj,
Func<T, T> fn,
string reason = "",
[CallerMemberName] string dbgName = "",
[CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression( "fn" )] string dbgExpression = "" )
where T : io.Recorded<T> // Catches Recorded and Timed
{
// This will call the 'Timed' override if T is Timed,
// or the 'Recorded' override if T is Recorded.
obj = obj.Process( fn, reason, dbgName, dbgPath, dbgLine, dbgExpression );
return obj;
}
public static string LogDiff<T>( T cur, T old, [CallerArgumentExpression( "cur" )] string dbgExpCur = "", [CallerArgumentExpression( "old" )] string dbgExpOld = "" )
/// <summary>
/// Processes a 'Versioned' object (Level 1).
/// </summary>
public static T LightProcess<T>(
ref T obj,
Func<T, T> fn,
string reason = "Processed" )
where T : io.Versioned<T>
{
return $"{dbgExpCur} changed from {old} to {cur}";
obj = obj.Process( fn, reason );
return obj;
}
// No specific Process needed for Timed, as it's caught by Recorded<T>
// and its Process override handles the timing.
/// <summary>
/// Processes a 'Recorded' object (Level 2), capturing caller info.
/// </summary>
public static T Process<T>(
ref T obj,
Func<T, T> fn,
string reason = "",
[CallerMemberName] string dbgName = "",
[CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression( "fn" )] string dbgExpression = "" )
where T : io.Recorded<T> // Catches Recorded and Timed
{
// This will call the 'Timed' override if T is Timed,
// or the 'Recorded' override if T is Recorded.
obj = obj.Process( fn, reason, dbgName, dbgPath, dbgLine, dbgExpression );
return obj;
}
public static string LogDiff<T>( T cur, T old, [CallerArgumentExpression( "cur" )] string dbgExpCur = "", [CallerArgumentExpression( "old" )] string dbgExpOld = "" )
{
return $"{dbgExpCur} changed from {old} to {cur}";
}
// No specific Process needed for Timed, as it's caught by Recorded<T>
// and its Process override handles the timing.
}

View File

@ -13,56 +13,56 @@ namespace io;
/// </summary>
public record class List<T> : Timed<List<T>>, IImmutableList<T>
{
static public List<T> Empty { get; } = new();
static public List<T> Empty { get; } = new();
public ImmutableList<T> Values { get; init; } = ImmutableList<T>.Empty;
public ImmutableList<T> Values { get; init; } = ImmutableList<T>.Empty;
public List() { }
// Required for 'with' expressions to work with the base class hierarchy
protected List(Timed<List<T>> original) : base(original) { }
public List() { }
// Required for 'with' expressions to work with the base class hierarchy
protected List( Timed<List<T>> original ) : base( original ) { }
// Helper to apply changes using the Process method
private List<T> Change(
Func<ImmutableList<T>, ImmutableList<T>> listChange,
[CallerMemberName] string dbgMethod = "",
[CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = -1,
[CallerArgumentExpression( "listChange" )] string reason = "" )
{
var newValues = listChange(Values);
return ReferenceEquals(Values, newValues)
? this
: Process(l => l with { Values = newValues }, reason, dbgMethod, dbgPath, dbgLine, reason);
}
// Helper to apply changes using the Process method
private List<T> Change(
Func<ImmutableList<T>, ImmutableList<T>> listChange,
[CallerMemberName] string dbgMethod = "",
[CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = -1,
[CallerArgumentExpression( "listChange" )] string reason = "" )
{
var newValues = listChange( Values );
return ReferenceEquals( Values, newValues )
? this
: Process( l => l with { Values = newValues }, reason, dbgMethod, dbgPath, dbgLine, reason );
}
// --- IImmutableList<T> implementation using the Change helper ---
public T this[int index] => Values[index];
public int Count => Values.Count;
// --- IImmutableList<T> implementation using the Change helper ---
public T this[int index] => Values[index];
public int Count => Values.Count;
public List<T> Add(T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.Add(value), dbgMethod, dbgPath, dbgLine);
public List<T> AddRange(IEnumerable<T> items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.AddRange(items), dbgMethod, dbgPath, dbgLine);
public List<T> Clear([CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.Clear(), dbgMethod, dbgPath, dbgLine);
#region IImmutableList Implementati, dbgMethod, dbgPath, dbgLineon
public List<T> Insert( int index, T element, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Insert( index, element ) , dbgMethod, dbgPath, dbgLine);
public List<T> InsertRange( int index, IEnumerable<T> items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.InsertRange( index, items ) , dbgMethod, dbgPath, dbgLine);
public List<T> Remove( T value, IEqualityComparer<T>? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Remove( value, equalityComparer ) , dbgMethod, dbgPath, dbgLine);
public List<T> Remove( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Remove( value, EqualityComparer<T>.Default , dbgMethod, dbgPath, dbgLine);
public List<T> RemoveAll( Predicate<T> match, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAll( match ) , dbgMethod, dbgPath, dbgLine);
public List<T> RemoveAt( int index, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAt( index ) , dbgMethod, dbgPath, dbgLine);
public List<T> RemoveRange( int index, int count, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( index, count ) , dbgMethod, dbgPath, dbgLine);
public List<T> RemoveRange( IEnumerable<T> items, IEqualityComparer<T>? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( items, equalityComparer ) , dbgMethod, dbgPath, dbgLine);
public List<T> Replace( T oldValue, T newValue, IEqualityComparer<T>? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Replace( oldValue, newValue, equalityComparer ) , dbgMethod, dbgPath, dbgLine);
public List<T> SetItem( int index, T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.SetItem( index, value ) , dbgMethod, dbgPath, dbgLine);
public List<T> Add( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Add( value ), dbgMethod, dbgPath, dbgLine );
public List<T> AddRange( IEnumerable<T> items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.AddRange( items ), dbgMethod, dbgPath, dbgLine );
public List<T> Clear( [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Clear(), dbgMethod, dbgPath, dbgLine );
#region IImmutableList Implementati, dbgMethod, dbgPath, dbgLineon
public List<T> Insert( int index, T element, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Insert( index, element ), dbgMethod, dbgPath, dbgLine );
public List<T> InsertRange( int index, IEnumerable<T> items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.InsertRange( index, items ), dbgMethod, dbgPath, dbgLine );
public List<T> Remove( T value, IEqualityComparer<T>? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Remove( value, equalityComparer ), dbgMethod, dbgPath, dbgLine );
public List<T> Remove( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Remove( value, EqualityComparer<T>.Default, dbgMethod, dbgPath, dbgLine );
public List<T> RemoveAll( Predicate<T> match, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAll( match ), dbgMethod, dbgPath, dbgLine );
public List<T> RemoveAt( int index, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAt( index ), dbgMethod, dbgPath, dbgLine );
public List<T> RemoveRange( int index, int count, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( index, count ), dbgMethod, dbgPath, dbgLine );
public List<T> RemoveRange( IEnumerable<T> items, IEqualityComparer<T>? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( items, equalityComparer ), dbgMethod, dbgPath, dbgLine );
public List<T> Replace( T oldValue, T newValue, IEqualityComparer<T>? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Replace( oldValue, newValue, equalityComparer ), dbgMethod, dbgPath, dbgLine );
public List<T> SetItem( int index, T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.SetItem( index, value ), dbgMethod, dbgPath, dbgLine );
public int IndexOf( T item, int index, int count, IEqualityComparer<T>? equalityComparer ) => Values.IndexOf( item, index, count, equalityComparer ?? EqualityComparer<T>.Default );
public int LastIndexOf( T item, int index, int count, IEqualityComparer<T>? equalityComparer) => Values.LastIndexOf( item, index, count, equalityComparer ?? EqualityComparer<T>.Default );
public int IndexOf( T item, int index, int count, IEqualityComparer<T>? equalityComparer ) => Values.IndexOf( item, index, count, equalityComparer ?? EqualityComparer<T>.Default );
public int LastIndexOf( T item, int index, int count, IEqualityComparer<T>? equalityComparer ) => Values.LastIndexOf( item, index, count, equalityComparer ?? EqualityComparer<T>.Default );
public int IndexOf( T item, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => IndexOf( item, 0, Count, EqualityComparer<T>.Default);
public int IndexOf( T item, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => IndexOf( item, 0, Count, EqualityComparer<T>.Default );
IImmutableList<T> IImmutableList<T>.Clear() => Clear();
IImmutableList<T> IImmutableList<T>.Clear() => Clear();
IImmutableList<T> IImmutableList<T>.Add( T value ) => Add( value );
IImmutableList<T> IImmutableList<T>.AddRange( IEnumerable<T> items ) => AddRange( items );
IImmutableList<T> IImmutableList<T>.Insert( int index, T element ) => Insert( index, element );
@ -74,9 +74,9 @@ public record class List<T> : Timed<List<T>>, IImmutableList<T>
IImmutableList<T> IImmutableList<T>.RemoveRange( int index, int count ) => RemoveRange( index, count );
IImmutableList<T> IImmutableList<T>.Replace( T oldValue, T newValue, IEqualityComparer<T>? equalityComparer ) => Replace( oldValue, newValue, equalityComparer );
IImmutableList<T> IImmutableList<T>.SetItem( int index, T value ) => SetItem( index, value );
#endregion
#endregion
// --- Standard Interfaces ---
public IEnumerator<T> GetEnumerator() => Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)Values).GetEnumerator();
// --- Standard Interfaces ---
public IEnumerator<T> GetEnumerator() => Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ( (IEnumerable)Values ).GetEnumerator();
}

View File

@ -261,7 +261,8 @@ public record class Recorded<T> : Versioned<T> where T : Recorded<T>
if( ReferenceEquals( current, next ) )
return current;
var newMeta = current.Meta with {
var newMeta = current.Meta with
{
Version = current.Meta.Version + 1,
Reason = reason,
MemberName = dbgName,

View File

@ -19,164 +19,164 @@ namespace ser;
public record CodeGenConfig : io.Recorded<CodeGenConfig>
{
// Whitelists (if needed, otherwise rely on attributes/defaults)
public ImmutableDictionary<string, ImmutableList<string>> WLProps { get; init; } = ImmutableDictionary<string, ImmutableList<string>>.Empty;
public ImmutableDictionary<string, ImmutableList<string>> WLFields { get; init; } = ImmutableDictionary<string, ImmutableList<string>>.Empty;
// Whitelists (if needed, otherwise rely on attributes/defaults)
public ImmutableDictionary<string, ImmutableList<string>> WLProps { get; init; } = ImmutableDictionary<string, ImmutableList<string>>.Empty;
public ImmutableDictionary<string, ImmutableList<string>> WLFields { get; init; } = ImmutableDictionary<string, ImmutableList<string>>.Empty;
// Default member types to process
public ser.Types TypesDefault { get; init; } = ser.Types.Fields | ser.Types.Props;
// Default member types to process
public ser.Types TypesDefault { get; init; } = ser.Types.Fields | ser.Types.Props;
// How to handle backing fields (might be less relevant for code gen)
public BackingFieldNaming Naming { get; init; } = BackingFieldNaming.Regular;
// How to handle backing fields (might be less relevant for code gen)
public BackingFieldNaming Naming { get; init; } = BackingFieldNaming.Regular;
public static CodeGenConfig Default { get; } = new CodeGenConfig();
public static CodeGenConfig Default { get; } = new CodeGenConfig();
}
public record GenMemberMeta(
MemberInfo Info,
Type Type,
string Name, // Name for code generation (usually original)
bool IsPrimitive,
bool IsCollection,
Type? CollectionElementType,
bool HasDo,
bool HasDont
MemberInfo Info,
Type Type,
string Name, // Name for code generation (usually original)
bool IsPrimitive,
bool IsCollection,
Type? CollectionElementType,
bool HasDo,
bool HasDont
);
public record TypeStructureInfo(
Type Type,
List<GenMemberMeta> Members,
bool IsValueType,
bool IsCollection
Type Type,
List<GenMemberMeta> Members,
bool IsValueType,
bool IsCollection
);
public class TypeStructureAnalyzer
{
private readonly ConcurrentDictionary<Type, TypeStructureInfo> _cache = new();
private readonly CodeGenConfig _cfg;
private readonly ConcurrentDictionary<Type, TypeStructureInfo> _cache = new();
private readonly CodeGenConfig _cfg;
public TypeStructureAnalyzer( CodeGenConfig cfg ) => _cfg = cfg;
public TypeStructureAnalyzer( CodeGenConfig cfg ) => _cfg = cfg;
public TypeStructureInfo Get( Type type ) => _cache.GetOrAdd( type, BuildTypeInfo );
public TypeStructureInfo Get( Type type ) => _cache.GetOrAdd( type, BuildTypeInfo );
private TypeStructureInfo BuildTypeInfo( Type type )
{
var members = new List<GenMemberMeta>();
var typesTodo = type.GetCustomAttribute<ser.Ser>( true )?.Types ?? _cfg.TypesDefault;
bool doFields = typesTodo.HasFlag( ser.Types.Fields );
bool doProps = typesTodo.HasFlag( ser.Types.Props );
private TypeStructureInfo BuildTypeInfo( Type type )
{
var members = new List<GenMemberMeta>();
var typesTodo = type.GetCustomAttribute<ser.Ser>( true )?.Types ?? _cfg.TypesDefault;
bool doFields = typesTodo.HasFlag( ser.Types.Fields );
bool doProps = typesTodo.HasFlag( ser.Types.Props );
// Track processed names to avoid duplicates (e.g., field + prop)
var processedNames = new HashSet<string>();
// Track processed names to avoid duplicates (e.g., field + prop)
var processedNames = new HashSet<string>();
// Process Properties First (often preferred interface)
if( doProps )
{
foreach( var pi in refl.GetAllProperties( type ) )
{
if( ProcessMember( pi, false, false, new HashSet<string>(), false, members ) )
{
processedNames.Add( pi.Name );
}
}
}
// Process Properties First (often preferred interface)
if( doProps )
{
foreach( var pi in refl.GetAllProperties( type ) )
{
if( ProcessMember( pi, false, false, new HashSet<string>(), false, members ) )
{
processedNames.Add( pi.Name );
}
}
}
// Process Fields, avoiding those already covered by properties
if( doFields )
{
foreach( var fi in refl.GetAllFields( type ) )
{
var (isBacking, propName) = IsBackingField( fi );
string nameToTest = isBacking ? propName : fi.Name;
// Process Fields, avoiding those already covered by properties
if( doFields )
{
foreach( var fi in refl.GetAllFields( type ) )
{
var (isBacking, propName) = IsBackingField( fi );
string nameToTest = isBacking ? propName : fi.Name;
if( !processedNames.Contains( nameToTest ) )
{
if( ProcessMember( fi, false, false, new HashSet<string>(), false, members ) )
{
processedNames.Add( nameToTest );
}
}
}
}
if( !processedNames.Contains( nameToTest ) )
{
if( ProcessMember( fi, false, false, new HashSet<string>(), false, members ) )
{
processedNames.Add( nameToTest );
}
}
}
}
return new TypeStructureInfo(
type,
members,
type.IsValueType,
typeof( IEnumerable ).IsAssignableFrom( type ) && type != typeof( string )
);
}
return new TypeStructureInfo(
type,
members,
type.IsValueType,
typeof( IEnumerable ).IsAssignableFrom( type ) && type != typeof( string )
);
}
private bool ProcessMember( MemberInfo mi, bool filter, bool doImpls, HashSet<string> whitelist, bool isImm, List<GenMemberMeta> members )
{
var (hasDo, hasDont, propName) = GetMemberAttributes( mi, out var actualMiForAtts );
private bool ProcessMember( MemberInfo mi, bool filter, bool doImpls, HashSet<string> whitelist, bool isImm, List<GenMemberMeta> members )
{
var (hasDo, hasDont, propName) = GetMemberAttributes( mi, out var actualMiForAtts );
if( hasDont )
return false;
if( mi.GetCustomAttribute<NonSerializedAttribute>( true ) != null )
return false;
if( mi.Name.Contains( "k__BackingField" ) && !propName.Any() )
return false; // Skip if backing but no prop found
if( hasDont )
return false;
if( mi.GetCustomAttribute<NonSerializedAttribute>( true ) != null )
return false;
if( mi.Name.Contains( "k__BackingField" ) && !propName.Any() )
return false; // Skip if backing but no prop found
string name = string.IsNullOrEmpty( propName ) ? mi.Name : propName;
string name = string.IsNullOrEmpty( propName ) ? mi.Name : propName;
// Add filtering logic if needed (based on whitelist, etc.)
// Add filtering logic if needed (based on whitelist, etc.)
var type = ( mi is FieldInfo fi ) ? fi.FieldType : ( (PropertyInfo)mi ).PropertyType;
bool isCollection = typeof( IEnumerable ).IsAssignableFrom( type ) && type != typeof( string );
Type? elementType = isCollection ? GetElementType( type ) : null;
bool isPrimitive = Type.GetTypeCode( type ) != TypeCode.Object && !isCollection;
var type = ( mi is FieldInfo fi ) ? fi.FieldType : ( (PropertyInfo)mi ).PropertyType;
bool isCollection = typeof( IEnumerable ).IsAssignableFrom( type ) && type != typeof( string );
Type? elementType = isCollection ? GetElementType( type ) : null;
bool isPrimitive = Type.GetTypeCode( type ) != TypeCode.Object && !isCollection;
members.Add( new GenMemberMeta(
mi, type, name, isPrimitive, isCollection, elementType, hasDo, hasDont
) );
return true;
}
members.Add( new GenMemberMeta(
mi, type, name, isPrimitive, isCollection, elementType, hasDo, hasDont
) );
return true;
}
private (bool, string) IsBackingField( FieldInfo fi )
{
if( fi.Name.StartsWith( "<" ) && fi.Name.EndsWith( "BackingField" ) )
{
var gtIndex = fi.Name.IndexOf( '>' );
if( gtIndex > 1 )
{
return (true, fi.Name.Substring( 1, gtIndex - 1 ));
}
}
return (false, "");
}
private (bool, string) IsBackingField( FieldInfo fi )
{
if( fi.Name.StartsWith( "<" ) && fi.Name.EndsWith( "BackingField" ) )
{
var gtIndex = fi.Name.IndexOf( '>' );
if( gtIndex > 1 )
{
return (true, fi.Name.Substring( 1, gtIndex - 1 ));
}
}
return (false, "");
}
private (bool hasDo, bool hasDont, string propName) GetMemberAttributes( MemberInfo mi, out MemberInfo actualMi )
{
actualMi = mi;
string propName = "";
if( mi is FieldInfo fi && IsBackingField( fi ).Item1 )
{
propName = IsBackingField( fi ).Item2;
var propInfo = mi.DeclaringType?.GetProperty( propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
if( propInfo != null )
actualMi = propInfo;
}
else if( mi is PropertyInfo )
{
propName = mi.Name;
}
private (bool hasDo, bool hasDont, string propName) GetMemberAttributes( MemberInfo mi, out MemberInfo actualMi )
{
actualMi = mi;
string propName = "";
if( mi is FieldInfo fi && IsBackingField( fi ).Item1 )
{
propName = IsBackingField( fi ).Item2;
var propInfo = mi.DeclaringType?.GetProperty( propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
if( propInfo != null )
actualMi = propInfo;
}
else if( mi is PropertyInfo )
{
propName = mi.Name;
}
return (
actualMi.GetCustomAttribute<ser.Do>() != null,
actualMi.GetCustomAttribute<ser.Dont>() != null,
propName
);
}
return (
actualMi.GetCustomAttribute<ser.Do>() != null,
actualMi.GetCustomAttribute<ser.Dont>() != null,
propName
);
}
private Type GetElementType( Type collectionType )
{
if( collectionType.IsArray )
return collectionType.GetElementType()!;
if( collectionType.IsGenericType )
return collectionType.GetGenericArguments().Last(); // Usually last (e.g., List<T>, Dict<K,V>)
return typeof( object ); // Fallback
}
private Type GetElementType( Type collectionType )
{
if( collectionType.IsArray )
return collectionType.GetElementType()!;
if( collectionType.IsGenericType )
return collectionType.GetGenericArguments().Last(); // Usually last (e.g., List<T>, Dict<K,V>)
return typeof( object ); // Fallback
}
// Add GetFilters and FilterField if needed, or simplify as above
// Add GetFilters and FilterField if needed, or simplify as above
}

View File

@ -139,7 +139,7 @@ namespace lib
private string fromStr = "";
void SetFromStr( Stream stream )
void SetFromStr( Stream stream )
{
fromStr = stream.ToString() ?? "{null}";
@ -186,7 +186,8 @@ namespace lib
doc.Load( reader );
if( doc.DocumentElement == null ) return null;
if( doc.DocumentElement == null )
return null;
if( t == null )
return Deserialize( doc.DocumentElement );
@ -256,7 +257,8 @@ namespace lib
{
TypeCode typeCode = Type.GetTypeCode( type );
if( _cfg.VerboseLogging ) log.info( $"{type.FriendlyName()}.{name} {existing} {mi?.Name}" );
if( _cfg.VerboseLogging )
log.info( $"{type.FriendlyName()}.{name} {existing} {mi?.Name}" );
if( typeCode != TypeCode.Object )
{
@ -276,7 +278,8 @@ namespace lib
if( obj is ser.I_Serialize iser )
{
if( _cfg.VerboseLogging ) log.info( $"" );
if( _cfg.VerboseLogging )
log.info( $"" );
obj = iser.OnDeserialize( null );
}
@ -314,7 +317,8 @@ namespace lib
private object DeserializeConcrete( XmlElement elem, MemberInfo mi, string name, Type type )
{
if( _cfg.VerboseLogging ) log.info( $"" );
if( _cfg.VerboseLogging )
log.info( $"" );
string val = "";
@ -398,7 +402,8 @@ namespace lib
private object HydrateObject( XmlElement elem, MemberInfo mi, Type finalType, object obj )
{
if( _cfg.VerboseLogging ) log.info( $"" );
if( _cfg.VerboseLogging )
log.info( $"" );
if( obj is IList )
{
@ -488,9 +493,10 @@ namespace lib
private object HydrateObjectOfNarrowType( XmlElement elem, MemberInfo mi, Type narrowType, object obj )
{
if( _cfg.VerboseLogging ) log.info( $"" );
if( _cfg.VerboseLogging )
log.info( $"" );
var isImm = typeof(io.Obj).IsAssignableFrom( narrowType );
var isImm = typeof( io.Obj ).IsAssignableFrom( narrowType );
XmlNodeList allChildren = elem.ChildNodes;
@ -536,7 +542,7 @@ namespace lib
name = refl.TypeToIdentifier( name );
// @@@ TODO This doesnt yet handle propNames!
if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) )
if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) )
continue;
var useFieldName = true;
@ -625,7 +631,7 @@ namespace lib
{
object existingObj = childPi.GetValue( obj );
object childObj = DeserializeConcrete( elem, childPi, name, childPi.PropertyType );
object childObj = DeserializeConcrete( elem, childPi, name, childPi.PropertyType );
if( setMethod != null )
{
@ -642,7 +648,7 @@ namespace lib
}
}
if(!isImm)
if( !isImm )
{
return obj;
}
@ -686,7 +692,8 @@ namespace lib
int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1;
if( _cfg.VerboseLogging ) log.info( $"{finalType?.FriendlyName()}({type?.FriendlyName()}) refInt {refInt} exitingObj = {obj?.ToString()}" );
if( _cfg.VerboseLogging )
log.info( $"{finalType?.FriendlyName()}({type?.FriendlyName()}) refInt {refInt} exitingObj = {obj?.ToString()}" );
obj = createObject( elem, finalType, refInt, obj );
@ -695,7 +702,8 @@ namespace lib
private object DeserializeList( XmlElement elem, MemberInfo mi, Type type, IList list )
{
if( _cfg.VerboseLogging ) log.info( $"" );
if( _cfg.VerboseLogging )
log.info( $"" );
XmlNodeList arrNodeList = elem.ChildNodes;
@ -731,7 +739,8 @@ namespace lib
typeElem = typeof( KeyValuePair<,> ).MakeGenericType( type.GenericTypeArguments );
}
if( _cfg.VerboseLogging ) log.info( $"DserCol {type.GetType().FriendlyName()} {typeElem.Name} into reflT {mi.ReflectedType.FriendlyName()} declT {mi.DeclaringType.FriendlyName()} {mi.Name}" );
if( _cfg.VerboseLogging )
log.info( $"DserCol {type.GetType().FriendlyName()} {typeElem.Name} into reflT {mi.ReflectedType.FriendlyName()} declT {mi.DeclaringType.FriendlyName()} {mi.Name}" );
string refString = elem.GetAttribute( "ref" );
int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1;
@ -776,7 +785,8 @@ namespace lib
var typeGen = Type.MakeGenericSignatureType( type );
if( _cfg.VerboseLogging ) log.info( $"TypeGen: {typeGen.FriendlyName()}" );
if( _cfg.VerboseLogging )
log.info( $"TypeGen: {typeGen.FriendlyName()}" );
if( type == typeof( ImmutableArray<> ).MakeGenericType( typeElem ) )
{
@ -833,7 +843,8 @@ namespace lib
private object DeserializeArray( XmlElement elem, MemberInfo mi, Type type )
{
if( _cfg.VerboseLogging ) log.info( $"" );
if( _cfg.VerboseLogging )
log.info( $"" );
Type typeElem = type.GetElementType();
@ -883,7 +894,8 @@ namespace lib
if( _cfg.datastructure == Datastructure.Graph && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) )
{
if( _cfg.VerboseLogging ) log.info( $"Reuse object" );
if( _cfg.VerboseLogging )
log.info( $"Reuse object" );
return m_alreadySerialized[refInt];
}
@ -893,7 +905,8 @@ namespace lib
if( isProxy )
{
if( _cfg.VerboseLogging ) log.info( $"use Proxy" );
if( _cfg.VerboseLogging )
log.info( $"use Proxy" );
object obj = null;
var tryType = type;
@ -937,7 +950,8 @@ namespace lib
if( isSubclass )
{
if( _cfg.VerboseLogging ) log.info( $"Using existing obj {existingObj?.ToString()}" );
if( _cfg.VerboseLogging )
log.info( $"Using existing obj {existingObj?.ToString()}" );
return existingObj;
}
@ -953,12 +967,14 @@ namespace lib
try
{
if( _cfg.VerboseLogging ) log.info( $"For {type.FriendlyName()} check for constructors" );
if( _cfg.VerboseLogging )
log.info( $"For {type.FriendlyName()} check for constructors" );
var cons = type.GetConstructor( Type.EmptyTypes );
if( cons != null)
if( cons != null )
{
if( _cfg.VerboseLogging ) log.info( $"Activator.CreateInstance" );
if( _cfg.VerboseLogging )
log.info( $"Activator.CreateInstance" );
obj = Activator.CreateInstance( type );
}
else
@ -967,15 +983,18 @@ namespace lib
obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type );
}
if( _cfg.VerboseLogging ) log.info( $"Got obj {obj?.ToString()}" );
if( _cfg.VerboseLogging )
log.info( $"Got obj {obj?.ToString()}" );
}
catch( Exception )
{
try
{
if( _cfg.VerboseLogging ) log.info( $"GetUninitializedObject" );
if( _cfg.VerboseLogging )
log.info( $"GetUninitializedObject" );
obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type );
if( _cfg.VerboseLogging ) log.info( $"Got obj {obj?.ToString()}" );
if( _cfg.VerboseLogging )
log.info( $"Got obj {obj?.ToString()}" );
}
catch( Exception exInner )
{
@ -1290,7 +1309,7 @@ namespace lib
HashSet<string> whitelistFields, whitelistProps;
GetFilters( _cfg.TypesDefault, mi, narrowType, out filterFields, out filterProps, out doImpls, out doFields, out doProps, out whitelistFields, out whitelistProps );
var isImm = typeof(io.Obj).IsAssignableFrom( narrowType );
var isImm = typeof( io.Obj ).IsAssignableFrom( narrowType );
if( doFields || doImpls )
{
@ -1323,8 +1342,10 @@ namespace lib
if( isImm )
{
if( name == "MetaStorage" ) continue;
if( name == "Fn" ) continue;
if( name == "MetaStorage" )
continue;
if( name == "Fn" )
continue;
}
if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) )
@ -1365,8 +1386,10 @@ namespace lib
if( isImm )
{
if( name == "MetaStorage" ) continue;
if( name == "Fn" ) continue;
if( name == "MetaStorage" )
continue;
if( name == "Fn" )
continue;
}
if( FilterField( filterProps, doImpls, whitelistProps, childPi as MemberInfo, name ) )
@ -1393,15 +1416,15 @@ namespace lib
var custWLProps = mi?.GetCustomAttribute<ser.ChildPropsAttribute>( true );
filterFields = custWLFields != null;
filterProps = custWLProps != null;
filterProps = custWLProps != null;
var typesTodo = type.GetCustomAttribute<ser.Ser>( true )?.Types ?? TypesDefault;
doImpls = typesTodo.HasFlag( ser.Types.Implied );
doImpls = typesTodo.HasFlag( ser.Types.Implied );
doFields = filterFields || typesTodo.HasFlag( ser.Types.Fields );
doProps = filterProps || typesTodo.HasFlag( ser.Types.Props );
doProps = filterProps || typesTodo.HasFlag( ser.Types.Props );
whitelistFields = new( custWLFields?.Values ?? new string[0] );
whitelistProps = new( custWLProps?.Values ?? new string[0] );
whitelistProps = new( custWLProps?.Values ?? new string[0] );
}
private void SerializeArray( XmlWriter writer, MemberInfo mi, Type mType, object root, int depth )
@ -1413,8 +1436,10 @@ namespace lib
Type type = root.GetType();
Type typeOfMember = typeof( object );
if( mi is FieldInfo fi ) typeOfMember = fi.FieldType;
if( mi is PropertyInfo pi ) typeOfMember = pi.PropertyType;
if( mi is FieldInfo fi )
typeOfMember = fi.FieldType;
if( mi is PropertyInfo pi )
typeOfMember = pi.PropertyType;
if( typeOfMember != type )
{
log.info( $"SerArr {typeOfMember.FriendlyName()} {mi?.Name} != {type.FriendlyName()}" );

View File

@ -174,14 +174,14 @@ static public class log
{
None = 0,
File = 1 << 0,
File = 1 << 0,
Console = 1 << 1,
All = File | Console,
}
#region LogEvent
#region LogEvent
public struct LogEvent
{
@ -256,7 +256,7 @@ static public class log
ImmutableInterlocked.AddOrUpdate( ref s_logEPforCat, cat, ep, ( k, v ) => ep );
}
#endregion // LogEvent
#endregion // LogEvent
static public void shutdown()
{
@ -299,7 +299,7 @@ static public class log
pathPieces = path.Split( '/' );
}
var lastPathPiece = pathPieces[pathPieces.Length - 1];
var lastPathPiece = pathPieces[pathPieces.Length - 1];
ImmutableInterlocked.AddOrUpdate( ref s_files, pathHash, lastPathPiece, ( key, value ) => { return lastPathPiece; } );
@ -396,32 +396,32 @@ static public class log
}
[StackTraceHidden]
static public void info( string msg, string cat = "",SourceLoc? loc = null,
static public void info( string msg, string cat = "", SourceLoc? loc = null,
[CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Info, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void debug( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
static public void debug( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Debug, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void trace( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
static public void trace( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Trace, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void warn( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
static public void warn( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Warn, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void high( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
static public void high( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.High, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
@ -456,12 +456,12 @@ static public class log
[StackTraceHidden]
static public void fatal( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
static public void fatal( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Fatal, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
//new LogEvent( LogType.Raw, $"", "", 0, "", "lib.time", "", null )
//new LogEvent( LogType.Raw, $"", "", 0, "", "lib.time", "", null )
#endregion
@ -523,7 +523,7 @@ static public class log
foreach( var fr in stackTrace.GetFrames() )
{
logBase( $"{fr.Log}", LogType.Raw );
logBase( $"{fr.Log}", LogType.Raw );
}
}
@ -546,14 +546,14 @@ static public class log
}
static public LogEvent logCreateEvent( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "",SourceLoc? loc = null )
static public LogEvent logCreateEvent( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "", SourceLoc? loc = null )
{
LogEvent evt = new LogEvent( type, msg, dbgPath, dbgLine, dbgMethod, cat, exp, loc );
return evt;
}
[StackTraceHidden]
static public void logBase( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "",SourceLoc? loc = null )
static public void logBase( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "", SourceLoc? loc = null )
{
var evt = logCreateEvent( msg, type, dbgPath, dbgLine, dbgMethod, cat, exp );

View File

@ -29,239 +29,239 @@ using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// A half precision (16 bit) floating point value.
/// </summary>
[DataContract]
[StructLayout( LayoutKind.Sequential, Pack = 2 )]
public struct Half
{
private ushort value;
/// <summary>
/// A half precision (16 bit) floating point value.
/// </summary>
[DataContract]
[StructLayout( LayoutKind.Sequential, Pack = 2 )]
public struct Half
{
private ushort value;
/// <summary>
/// Number of decimal digits of precision.
/// </summary>
public const int PrecisionDigits = 3;
/// <summary>
/// Number of decimal digits of precision.
/// </summary>
public const int PrecisionDigits = 3;
/// <summary>
/// Number of bits in the mantissa.
/// </summary>
public const int MantissaBits = 11;
/// <summary>
/// Number of bits in the mantissa.
/// </summary>
public const int MantissaBits = 11;
/// <summary>
/// Maximum decimal exponent.
/// </summary>
public const int MaximumDecimalExponent = 4;
/// <summary>
/// Maximum decimal exponent.
/// </summary>
public const int MaximumDecimalExponent = 4;
/// <summary>
/// Maximum binary exponent.
/// </summary>
public const int MaximumBinaryExponent = 15;
/// <summary>
/// Maximum binary exponent.
/// </summary>
public const int MaximumBinaryExponent = 15;
/// <summary>
/// Minimum decimal exponent.
/// </summary>
public const int MinimumDecimalExponent = -4;
/// <summary>
/// Minimum decimal exponent.
/// </summary>
public const int MinimumDecimalExponent = -4;
/// <summary>
/// Minimum binary exponent.
/// </summary>
public const int MinimumBinaryExponent = -14;
/// <summary>
/// Minimum binary exponent.
/// </summary>
public const int MinimumBinaryExponent = -14;
/// <summary>
/// Exponent radix.
/// </summary>
public const int ExponentRadix = 2;
/// <summary>
/// Exponent radix.
/// </summary>
public const int ExponentRadix = 2;
/// <summary>
/// Additional rounding.
/// </summary>
public const int AdditionRounding = 1;
/// <summary>
/// Additional rounding.
/// </summary>
public const int AdditionRounding = 1;
/// <summary>
/// Smallest such that 1.0 + epsilon != 1.0
/// </summary>
public static readonly float Epsilon;
/// <summary>
/// Smallest such that 1.0 + epsilon != 1.0
/// </summary>
public static readonly float Epsilon;
/// <summary>
/// Maximum value of the number.
/// </summary>
public static readonly float MaxValue;
/// <summary>
/// Maximum value of the number.
/// </summary>
public static readonly float MaxValue;
/// <summary>
/// Minimum value of the number.
/// </summary>
public static readonly float MinValue;
/// <summary>
/// Minimum value of the number.
/// </summary>
public static readonly float MinValue;
/// <summary>
/// A <see cref="Half"/> whose value is 0.0f.
/// </summary>
public static readonly Half Zero;
/// <summary>
/// A <see cref="Half"/> whose value is 0.0f.
/// </summary>
public static readonly Half Zero;
/// <summary>
/// A <see cref="Half"/> whose value is 1.0f.
/// </summary>
public static readonly Half One;
/// <summary>
/// A <see cref="Half"/> whose value is 1.0f.
/// </summary>
public static readonly Half One;
/// <summary>
/// Initializes a new instance of the <see cref="Half"/> structure.
/// </summary>
/// <param name = "value">The floating point value that should be stored in 16 bit format.</param>
public Half( float value )
{
this.value = HalfUtils.Pack( value );
}
/// <summary>
/// Initializes a new instance of the <see cref="Half"/> structure.
/// </summary>
/// <param name = "value">The floating point value that should be stored in 16 bit format.</param>
public Half( float value )
{
this.value = HalfUtils.Pack( value );
}
/// <summary>
/// Gets or sets the raw 16 bit value used to back this half-float.
/// </summary>
public ushort RawValue
{
get { return value; }
set { this.value = value; }
}
/// <summary>
/// Gets or sets the raw 16 bit value used to back this half-float.
/// </summary>
public ushort RawValue
{
get { return value; }
set { this.value = value; }
}
/// <summary>
/// Converts an array of half precision values into full precision values.
/// </summary>
/// <param name = "values">The values to be converted.</param>
/// <returns>An array of converted values.</returns>
public static float[] ConvertToFloat( Half[] values )
{
float[] results = new float[values.Length];
for( int i = 0; i < results.Length; i++ )
results[i] = HalfUtils.Unpack( values[i].RawValue );
return results;
}
/// <summary>
/// Converts an array of half precision values into full precision values.
/// </summary>
/// <param name = "values">The values to be converted.</param>
/// <returns>An array of converted values.</returns>
public static float[] ConvertToFloat( Half[] values )
{
float[] results = new float[values.Length];
for( int i = 0; i < results.Length; i++ )
results[i] = HalfUtils.Unpack( values[i].RawValue );
return results;
}
/// <summary>
/// Converts an array of full precision values into half precision values.
/// </summary>
/// <param name = "values">The values to be converted.</param>
/// <returns>An array of converted values.</returns>
public static Half[] ConvertToHalf( float[] values )
{
Half[] results = new Half[values.Length];
for( int i = 0; i < results.Length; i++ )
results[i] = new Half( values[i] );
return results;
}
/// <summary>
/// Converts an array of full precision values into half precision values.
/// </summary>
/// <param name = "values">The values to be converted.</param>
/// <returns>An array of converted values.</returns>
public static Half[] ConvertToHalf( float[] values )
{
Half[] results = new Half[values.Length];
for( int i = 0; i < results.Length; i++ )
results[i] = new Half( values[i] );
return results;
}
/// <summary>
/// Performs an explicit conversion from <see cref = "T:System.Single" /> to <see cref = "T:math.Half" />.
/// </summary>
/// <param name = "value">The value to be converted.</param>
/// <returns>The converted value.</returns>
public static explicit operator Half( float value )
{
return new Half( value );
}
/// <summary>
/// Performs an explicit conversion from <see cref = "T:System.Single" /> to <see cref = "T:math.Half" />.
/// </summary>
/// <param name = "value">The value to be converted.</param>
/// <returns>The converted value.</returns>
public static explicit operator Half( float value )
{
return new Half( value );
}
/// <summary>
/// Performs an implicit conversion from <see cref = "T:math.Half" /> to <see cref = "T:System.Single" />.
/// </summary>
/// <param name = "value">The value to be converted.</param>
/// <returns>The converted value.</returns>
public static implicit operator float( Half value )
{
return HalfUtils.Unpack( value.value );
}
/// <summary>
/// Performs an implicit conversion from <see cref = "T:math.Half" /> to <see cref = "T:System.Single" />.
/// </summary>
/// <param name = "value">The value to be converted.</param>
/// <returns>The converted value.</returns>
public static implicit operator float( Half value )
{
return HalfUtils.Unpack( value.value );
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name = "left" /> has the same value as <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==( Half left, Half right )
{
return left.value == right.value;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name = "left" /> has the same value as <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==( Half left, Half right )
{
return left.value == right.value;
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name = "left" /> has a different value than <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=( Half left, Half right )
{
return left.value != right.value;
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name = "left" /> has a different value than <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=( Half left, Half right )
{
return left.value != right.value;
}
/// <summary>
/// Converts the value of the object to its equivalent string representation.
/// </summary>
/// <returns>The string representation of the value of this instance.</returns>
public override string ToString()
{
float num = this;
return num.ToString( CultureInfo.CurrentCulture );
}
/// <summary>
/// Converts the value of the object to its equivalent string representation.
/// </summary>
/// <returns>The string representation of the value of this instance.</returns>
public override string ToString()
{
float num = this;
return num.ToString( CultureInfo.CurrentCulture );
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
ushort num = value;
return ( ( num * 3 ) / 2 ) ^ num;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
ushort num = value;
return ( ( num * 3 ) / 2 ) ^ num;
}
/// <summary>
/// Determines whether the specified object instances are considered equal.
/// </summary>
/// <param name = "value1">The first value.</param>
/// <param name = "value2">The second value.</param>
/// <returns>
/// <c>true</c> if <paramref name = "value1" /> is the same instance as <paramref name = "value2" /> or
/// if both are <c>null</c> references or if <c>value1.Equals(value2)</c> returns <c>true</c>; otherwise, <c>false</c>.</returns>
public static bool Equals( ref Half value1, ref Half value2 )
{
return value1.value == value2.value;
}
/// <summary>
/// Determines whether the specified object instances are considered equal.
/// </summary>
/// <param name = "value1">The first value.</param>
/// <param name = "value2">The second value.</param>
/// <returns>
/// <c>true</c> if <paramref name = "value1" /> is the same instance as <paramref name = "value2" /> or
/// if both are <c>null</c> references or if <c>value1.Equals(value2)</c> returns <c>true</c>; otherwise, <c>false</c>.</returns>
public static bool Equals( ref Half value1, ref Half value2 )
{
return value1.value == value2.value;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to the specified object.
/// </summary>
/// <param name = "other">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public bool Equals( Half other )
{
return other.value == value;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to the specified object.
/// </summary>
/// <param name = "other">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public bool Equals( Half other )
{
return other.value == value;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name = "obj">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public override bool Equals( object obj )
{
if( obj == null )
{
return false;
}
if( obj.GetType() != GetType() )
{
return false;
}
Half half = (Half)obj;
return half.value == value;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name = "obj">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public override bool Equals( object obj )
{
if( obj == null )
{
return false;
}
if( obj.GetType() != GetType() )
{
return false;
}
Half half = (Half)obj;
return half.value == value;
}
static Half()
{
Epsilon = 0.0004887581f;
MaxValue = 65504f;
MinValue = 6.103516E-05f;
Zero = (Half)0.0f;
One = (Half)1.0f;
}
}
static Half()
{
Epsilon = 0.0004887581f;
MaxValue = 65504f;
MinValue = 6.103516E-05f;
Zero = (Half)0.0f;
One = (Half)1.0f;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -27,108 +27,108 @@ using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Defines a 2D rectangular size (width,height).
/// </summary>
[DataContract( Name = "Size2F" )]
[DataStyle( DataStyle.Compact )]
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
public struct Size2F : IEquatable<Size2F>
{
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2F Zero = new Size2F( 0, 0 );
/// <summary>
/// Defines a 2D rectangular size (width,height).
/// </summary>
[DataContract( Name = "Size2F" )]
[DataStyle( DataStyle.Compact )]
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
public struct Size2F : IEquatable<Size2F>
{
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2F Zero = new Size2F( 0, 0 );
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2F Empty = Zero;
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2F Empty = Zero;
/// <summary>
/// Initializes a new instance of the <see cref="Size2F"/> struct.
/// </summary>
/// <param name="width">The x.</param>
/// <param name="height">The y.</param>
public Size2F( float width, float height )
{
Width = width;
Height = height;
}
/// <summary>
/// Initializes a new instance of the <see cref="Size2F"/> struct.
/// </summary>
/// <param name="width">The x.</param>
/// <param name="height">The y.</param>
public Size2F( float width, float height )
{
Width = width;
Height = height;
}
/// <summary>
/// Width.
/// </summary>
[DataMember( Order = 0 )]
public float Width;
/// <summary>
/// Width.
/// </summary>
[DataMember( Order = 0 )]
public float Width;
/// <summary>
/// Height.
/// </summary>
[DataMember( Order = 1 )]
public float Height;
/// <summary>
/// Height.
/// </summary>
[DataMember( Order = 1 )]
public float Height;
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals( Size2F other )
{
return other.Width == Width && other.Height == Height;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals( Size2F other )
{
return other.Width == Width && other.Height == Height;
}
/// <inheritdoc/>
public override bool Equals( object obj )
{
if( ReferenceEquals( null, obj ) )
return false;
if( obj.GetType() != typeof( Size2F ) )
return false;
return Equals( (Size2F)obj );
}
/// <inheritdoc/>
public override bool Equals( object obj )
{
if( ReferenceEquals( null, obj ) )
return false;
if( obj.GetType() != typeof( Size2F ) )
return false;
return Equals( (Size2F)obj );
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return ( Width.GetHashCode() * 397 ) ^ Height.GetHashCode();
}
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return ( Width.GetHashCode() * 397 ) ^ Height.GetHashCode();
}
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==( Size2F left, Size2F right )
{
return left.Equals( right );
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==( Size2F left, Size2F right )
{
return left.Equals( right );
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=( Size2F left, Size2F right )
{
return !left.Equals( right );
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=( Size2F left, Size2F right )
{
return !left.Equals( right );
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format( "({0},{1})", Width, Height );
}
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format( "({0},{1})", Width, Height );
}
}
}

View File

@ -2,63 +2,63 @@
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
namespace math
{
/// <summary>
/// Extensions methods of the vector classes.
/// </summary>
public static class VectorExtensions
{
/// <summary>
/// Return the Y/X components of the vector in the inverse order.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 YX( this Vec2 vector )
{
return new Vec2( vector.Y, vector.X );
}
/// <summary>
/// Extensions methods of the vector classes.
/// </summary>
public static class VectorExtensions
{
/// <summary>
/// Return the Y/X components of the vector in the inverse order.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 YX( this Vec2 vector )
{
return new Vec2( vector.Y, vector.X );
}
/// <summary>
/// Return the X/Y components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XY( this Vec3 vector )
{
return new Vec2( vector.X, vector.Y );
}
/// <summary>
/// Return the X/Y components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XY( this Vec3 vector )
{
return new Vec2( vector.X, vector.Y );
}
/// <summary>
/// Return the X/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XZ( this Vec3 vector )
{
return new Vec2( vector.X, vector.Z );
}
/// <summary>
/// Return the X/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XZ( this Vec3 vector )
{
return new Vec2( vector.X, vector.Z );
}
/// <summary>
/// Return the Y/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 YZ( this Vec3 vector )
{
return new Vec2( vector.Y, vector.Z );
}
/// <summary>
/// Return the Y/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 YZ( this Vec3 vector )
{
return new Vec2( vector.Y, vector.Z );
}
/// <summary>
/// Return the X/Y components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XY( this Vec4 vector )
{
return new Vec2( vector.X, vector.Y );
}
/// <summary>
/// Return the X/Y components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XY( this Vec4 vector )
{
return new Vec2( vector.X, vector.Y );
}
/// <summary>
/// Return the X/Y/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec3 XYZ( this Vec4 vector )
{
return new Vec3( vector.X, vector.Y, vector.Z );
}
}
/// <summary>
/// Return the X/Y/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec3 XYZ( this Vec4 vector )
{
return new Vec3( vector.X, vector.Y, vector.Z );
}
}
}

View File

@ -182,7 +182,7 @@ public class Ref<T> : Ref where T : class, new()
// Let's assume you'll add saving logic here.
// Mgr.Save(value, path); // Example: Needs implementation
var immMeta = (value as io.Obj)?.Meta;
var immMeta = ( value as io.Obj )?.Meta;
@ -433,7 +433,7 @@ public static class Mgr
var loadedObject = loaderHolder.Load( filename, reason, dbgName, dbgPath, dbgLine );
if( loadedObject is T value )
{
var meta = (value as io.Obj)?.Meta;
var meta = ( value as io.Obj )?.Meta;
// If it's an immutable object, record its loading.
if( value is io.Obj imm )

View File

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0