Formats UO Content (#201)

This commit is contained in:
Kamron Batman 2020-08-27 18:30:38 -07:00 • committed by GitHub
parent 86b7b3aed1
commit ad3775c4d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3249 changed files with 431083 additions and 440981 deletions

View file

@ -1,130 +1,130 @@
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public delegate BaseExtension ExtensionConstructor();
public sealed class ExtensionInfo
{
public ExtensionInfo(int order, string name, int size, ExtensionConstructor constructor)
{
Name = name;
Size = size;
Order = order;
Constructor = constructor;
}
public static Dictionary<string, ExtensionInfo> Table { get; } =
new Dictionary<string, ExtensionInfo>(StringComparer.InvariantCultureIgnoreCase);
public int Order { get; }
public string Name { get; }
public int Size { get; }
public bool IsFixedSize => Size >= 0;
public ExtensionConstructor Constructor { get; }
public static void Register(ExtensionInfo ext)
{
Table[ext.Name] = ext;
}
}
public sealed class Extensions : List<BaseExtension>
{
public bool IsValid(object obj)
{
for (int i = 0; i < Count; ++i)
if (!this[i].IsValid(obj))
return false;
return true;
}
public void Filter(List<object> list)
{
for (int i = 0; i < Count; ++i)
this[i].Filter(list);
}
public static Extensions Parse(Mobile from, ref string[] args)
{
Extensions parsed = new Extensions();
int size = args.Length;
Type baseType = null;
for (int i = args.Length - 1; i >= 0; --i)
{
if (!ExtensionInfo.Table.TryGetValue(args[i], out ExtensionInfo extInfo))
continue;
if (extInfo.IsFixedSize && i != size - extInfo.Size - 1)
throw new Exception("Invalid extended argument count.");
BaseExtension ext = extInfo.Constructor();
ext.Parse(from, args, i + 1, size - i - 1);
if (ext is WhereExtension extension)
baseType = extension.Conditional.Type;
parsed.Add(ext);
size = i;
}
parsed.Sort((a, b) => a.Order - b.Order);
AssemblyEmitter emitter = null;
foreach (BaseExtension update in parsed)
update.Optimize(from, baseType, ref emitter);
if (size != args.Length)
{
string[] old = args;
args = new string[size];
for (int i = 0; i < args.Length; ++i)
args[i] = old[i];
}
return parsed;
}
}
public abstract class BaseExtension
{
public abstract ExtensionInfo Info { get; }
public string Name => Info.Name;
public int Size => Info.Size;
public bool IsFixedSize => Info.IsFixedSize;
public int Order => Info.Order;
public virtual void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
}
public virtual void Parse(Mobile from, string[] arguments, int offset, int size)
{
}
public virtual bool IsValid(object obj) => true;
public virtual void Filter(List<object> list)
{
}
}
}
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public delegate BaseExtension ExtensionConstructor();
public sealed class ExtensionInfo
{
public ExtensionInfo(int order, string name, int size, ExtensionConstructor constructor)
{
Name = name;
Size = size;
Order = order;
Constructor = constructor;
}
public static Dictionary<string, ExtensionInfo> Table { get; } =
new Dictionary<string, ExtensionInfo>(StringComparer.InvariantCultureIgnoreCase);
public int Order { get; }
public string Name { get; }
public int Size { get; }
public bool IsFixedSize => Size >= 0;
public ExtensionConstructor Constructor { get; }
public static void Register(ExtensionInfo ext)
{
Table[ext.Name] = ext;
}
}
public sealed class Extensions : List<BaseExtension>
{
public bool IsValid(object obj)
{
for (var i = 0; i < Count; ++i)
if (!this[i].IsValid(obj))
return false;
return true;
}
public void Filter(List<object> list)
{
for (var i = 0; i < Count; ++i)
this[i].Filter(list);
}
public static Extensions Parse(Mobile from, ref string[] args)
{
var parsed = new Extensions();
var size = args.Length;
Type baseType = null;
for (var i = args.Length - 1; i >= 0; --i)
{
if (!ExtensionInfo.Table.TryGetValue(args[i], out var extInfo))
continue;
if (extInfo.IsFixedSize && i != size - extInfo.Size - 1)
throw new Exception("Invalid extended argument count.");
var ext = extInfo.Constructor();
ext.Parse(from, args, i + 1, size - i - 1);
if (ext is WhereExtension extension)
baseType = extension.Conditional.Type;
parsed.Add(ext);
size = i;
}
parsed.Sort((a, b) => a.Order - b.Order);
AssemblyEmitter emitter = null;
foreach (var update in parsed)
update.Optimize(from, baseType, ref emitter);
if (size != args.Length)
{
var old = args;
args = new string[size];
for (var i = 0; i < args.Length; ++i)
args[i] = old[i];
}
return parsed;
}
}
public abstract class BaseExtension
{
public abstract ExtensionInfo Info { get; }
public string Name => Info.Name;
public int Size => Info.Size;
public bool IsFixedSize => Info.IsFixedSize;
public int Order => Info.Order;
public virtual void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
}
public virtual void Parse(Mobile from, string[] arguments, int offset, int size)
{
}
public virtual bool IsValid(object obj) => true;
public virtual void Filter(List<object> list)
{
}
}
}

View file

@ -1,224 +1,250 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using Server.Utilities;
namespace Server.Commands.Generic
{
public static class DistinctCompiler
{
public static IComparer<T> Compile<T>(AssemblyEmitter assembly, Type objectType, Property[] props)
{
TypeBuilder typeBuilder = assembly.DefineType(
"__distinct",
TypeAttributes.Public,
typeof(object));
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes);
ILGenerator il = ctor.GetILGenerator();
// : base()
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, typeof(T).GetConstructor(Type.EmptyTypes) ??
throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}"));
// return;
il.Emit(OpCodes.Ret);
}
typeBuilder.AddInterfaceImplementation(typeof(IComparer<T>));
MethodBuilder compareMethod;
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "Compare",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(int),
/* params */ new[] { typeof(T), typeof(T) });
LocalBuilder a = emitter.CreateLocal(objectType);
LocalBuilder b = emitter.CreateLocal(objectType);
LocalBuilder v = emitter.CreateLocal(typeof(int));
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(a);
emitter.LoadArgument(2);
emitter.CastAs(objectType);
emitter.StoreLocal(b);
emitter.Load(0);
emitter.StoreLocal(v);
Label end = emitter.CreateLabel();
for (int i = 0; i < props.Length; ++i)
{
if (i > 0)
{
emitter.LoadLocal(v);
emitter.BranchIfTrue(end);
}
Property prop = props[i];
emitter.LoadLocal(a);
emitter.Chain(prop);
bool couldCompare =
emitter.CompareTo(1, () =>
{
emitter.LoadLocal(b);
emitter.Chain(prop);
});
if (!couldCompare)
throw new InvalidOperationException("Property is not comparable.");
emitter.StoreLocal(v);
}
emitter.MarkLabel(end);
emitter.LoadLocal(v);
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IComparer<T>).GetMethod(
"Compare",
new[]
{
typeof(T),
typeof(T)
}) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}"));
compareMethod = emitter.Method;
}
typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer<T>));
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "Equals",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(bool),
/* params */ new[] { typeof(T), typeof(T) });
emitter.Generator.Emit(OpCodes.Ldarg_0);
emitter.Generator.Emit(OpCodes.Ldarg_1);
emitter.Generator.Emit(OpCodes.Ldarg_2);
emitter.Generator.Emit(OpCodes.Call, compareMethod);
emitter.Generator.Emit(OpCodes.Ldc_I4_0);
emitter.Generator.Emit(OpCodes.Ceq);
emitter.Generator.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IEqualityComparer<T>).GetMethod(
"Equals",
new[]
{
typeof(T),
typeof(T)
}) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}"));
}
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "GetHashCode",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(int),
/* params */ new[] { typeof(T) });
LocalBuilder obj = emitter.CreateLocal(objectType);
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(obj);
for (int i = 0; i < props.Length; ++i)
{
Property prop = props[i];
emitter.LoadLocal(obj);
emitter.Chain(prop);
Type active = emitter.Active;
MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);
getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes);
if (active != typeof(int))
{
if (!active.IsValueType)
{
LocalBuilder value = emitter.AcquireTemp(active);
Label valueNotNull = emitter.CreateLabel();
Label done = emitter.CreateLabel();
emitter.StoreLocal(value);
emitter.LoadLocal(value);
emitter.BranchIfTrue(valueNotNull);
emitter.Load(0);
emitter.Pop(typeof(int));
emitter.Branch(done);
emitter.MarkLabel(valueNotNull);
emitter.LoadLocal(value);
emitter.Call(getHashCode);
emitter.ReleaseTemp(value);
emitter.MarkLabel(done);
}
else
{
emitter.Call(getHashCode);
}
}
if (i > 0)
emitter.Xor();
}
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IEqualityComparer<T>).GetMethod(
"GetHashCode",
new[]
{
typeof(T)
}) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}"));
}
Type comparerType = typeBuilder.CreateType();
return (IComparer<T>)ActivatorUtil.CreateInstance(comparerType);
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using Server.Utilities;
namespace Server.Commands.Generic
{
public static class DistinctCompiler
{
public static IComparer<T> Compile<T>(AssemblyEmitter assembly, Type objectType, Property[] props)
{
var typeBuilder = assembly.DefineType(
"__distinct",
TypeAttributes.Public,
typeof(object)
);
{
var ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes
);
var il = ctor.GetILGenerator();
// : base()
il.Emit(OpCodes.Ldarg_0);
il.Emit(
OpCodes.Call,
typeof(T).GetConstructor(Type.EmptyTypes) ??
throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}")
);
// return;
il.Emit(OpCodes.Ret);
}
typeBuilder.AddInterfaceImplementation(typeof(IComparer<T>));
MethodBuilder compareMethod;
{
var emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "Compare",
/* attr */
MethodAttributes.Public | MethodAttributes.Virtual,
/* return */
typeof(int),
/* params */
new[] { typeof(T), typeof(T) }
);
var a = emitter.CreateLocal(objectType);
var b = emitter.CreateLocal(objectType);
var v = emitter.CreateLocal(typeof(int));
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(a);
emitter.LoadArgument(2);
emitter.CastAs(objectType);
emitter.StoreLocal(b);
emitter.Load(0);
emitter.StoreLocal(v);
var end = emitter.CreateLabel();
for (var i = 0; i < props.Length; ++i)
{
if (i > 0)
{
emitter.LoadLocal(v);
emitter.BranchIfTrue(end);
}
var prop = props[i];
emitter.LoadLocal(a);
emitter.Chain(prop);
var couldCompare =
emitter.CompareTo(
1,
() =>
{
emitter.LoadLocal(b);
emitter.Chain(prop);
}
);
if (!couldCompare)
throw new InvalidOperationException("Property is not comparable.");
emitter.StoreLocal(v);
}
emitter.MarkLabel(end);
emitter.LoadLocal(v);
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IComparer<T>).GetMethod(
"Compare",
new[]
{
typeof(T),
typeof(T)
}
) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}")
);
compareMethod = emitter.Method;
}
typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer<T>));
{
var emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "Equals",
/* attr */
MethodAttributes.Public | MethodAttributes.Virtual,
/* return */
typeof(bool),
/* params */
new[] { typeof(T), typeof(T) }
);
emitter.Generator.Emit(OpCodes.Ldarg_0);
emitter.Generator.Emit(OpCodes.Ldarg_1);
emitter.Generator.Emit(OpCodes.Ldarg_2);
emitter.Generator.Emit(OpCodes.Call, compareMethod);
emitter.Generator.Emit(OpCodes.Ldc_I4_0);
emitter.Generator.Emit(OpCodes.Ceq);
emitter.Generator.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IEqualityComparer<T>).GetMethod(
"Equals",
new[]
{
typeof(T),
typeof(T)
}
) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}")
);
}
{
var emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "GetHashCode",
/* attr */
MethodAttributes.Public | MethodAttributes.Virtual,
/* return */
typeof(int),
/* params */
new[] { typeof(T) }
);
var obj = emitter.CreateLocal(objectType);
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(obj);
for (var i = 0; i < props.Length; ++i)
{
var prop = props[i];
emitter.LoadLocal(obj);
emitter.Chain(prop);
var active = emitter.Active;
var getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);
getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes);
if (active != typeof(int))
{
if (!active.IsValueType)
{
var value = emitter.AcquireTemp(active);
var valueNotNull = emitter.CreateLabel();
var done = emitter.CreateLabel();
emitter.StoreLocal(value);
emitter.LoadLocal(value);
emitter.BranchIfTrue(valueNotNull);
emitter.Load(0);
emitter.Pop(typeof(int));
emitter.Branch(done);
emitter.MarkLabel(valueNotNull);
emitter.LoadLocal(value);
emitter.Call(getHashCode);
emitter.ReleaseTemp(value);
emitter.MarkLabel(done);
}
else
{
emitter.Call(getHashCode);
}
}
if (i > 0)
emitter.Xor();
}
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IEqualityComparer<T>).GetMethod(
"GetHashCode",
new[]
{
typeof(T)
}
) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}")
);
}
var comparerType = typeBuilder.CreateType();
return (IComparer<T>)ActivatorUtil.CreateInstance(comparerType);
}
}
}

View file

@ -1,149 +1,163 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using Server.Utilities;
namespace Server.Commands.Generic
{
public sealed class OrderInfo
{
private int m_Order;
public OrderInfo(Property property, bool isAscending)
{
Property = property;
IsAscending = isAscending;
}
public Property Property { get; set; }
public bool IsAscending
{
get => m_Order > 0;
set => m_Order = value ? +1 : -1;
}
public bool IsDescending
{
get => m_Order < 0;
set => m_Order = value ? -1 : +1;
}
public int Sign
{
get => Math.Sign(m_Order);
set
{
m_Order = Math.Sign(value);
if (m_Order == 0)
throw new InvalidOperationException("Sign cannot be zero.");
}
}
}
public static class SortCompiler
{
public static IComparer<T> Compile<T>(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
{
TypeBuilder typeBuilder = assembly.DefineType(
"__sort",
TypeAttributes.Public,
typeof(T));
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes);
ILGenerator il = ctor.GetILGenerator();
// : base()
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, typeof(T).GetConstructor(Type.EmptyTypes) ??
throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}"));
// return;
il.Emit(OpCodes.Ret);
}
typeBuilder.AddInterfaceImplementation(typeof(IComparer<T>));
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "Compare",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(int),
/* params */ new[] { typeof(T), typeof(T) });
LocalBuilder a = emitter.CreateLocal(objectType);
LocalBuilder b = emitter.CreateLocal(objectType);
LocalBuilder v = emitter.CreateLocal(typeof(int));
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(a);
emitter.LoadArgument(2);
emitter.CastAs(objectType);
emitter.StoreLocal(b);
emitter.Load(0);
emitter.StoreLocal(v);
Label end = emitter.CreateLabel();
for (int i = 0; i < orders.Length; ++i)
{
if (i > 0)
{
emitter.LoadLocal(v);
emitter.BranchIfTrue(end);
}
OrderInfo orderInfo = orders[i];
Property prop = orderInfo.Property;
int sign = orderInfo.Sign;
emitter.LoadLocal(a);
emitter.Chain(prop);
bool couldCompare =
emitter.CompareTo(sign, () =>
{
emitter.LoadLocal(b);
emitter.Chain(prop);
});
if (!couldCompare)
throw new InvalidOperationException("Property is not comparable.");
emitter.StoreLocal(v);
}
emitter.MarkLabel(end);
emitter.LoadLocal(v);
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IComparer<T>).GetMethod(
"Compare",
new[]
{
typeof(T),
typeof(T)
}) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}"));
}
Type comparerType = typeBuilder.CreateType();
return (IComparer<T>)ActivatorUtil.CreateInstance(comparerType);
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using Server.Utilities;
namespace Server.Commands.Generic
{
public sealed class OrderInfo
{
private int m_Order;
public OrderInfo(Property property, bool isAscending)
{
Property = property;
IsAscending = isAscending;
}
public Property Property { get; set; }
public bool IsAscending
{
get => m_Order > 0;
set => m_Order = value ? +1 : -1;
}
public bool IsDescending
{
get => m_Order < 0;
set => m_Order = value ? -1 : +1;
}
public int Sign
{
get => Math.Sign(m_Order);
set
{
m_Order = Math.Sign(value);
if (m_Order == 0)
throw new InvalidOperationException("Sign cannot be zero.");
}
}
}
public static class SortCompiler
{
public static IComparer<T> Compile<T>(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
{
var typeBuilder = assembly.DefineType(
"__sort",
TypeAttributes.Public,
typeof(T)
);
{
var ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes
);
var il = ctor.GetILGenerator();
// : base()
il.Emit(OpCodes.Ldarg_0);
il.Emit(
OpCodes.Call,
typeof(T).GetConstructor(Type.EmptyTypes) ??
throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}")
);
// return;
il.Emit(OpCodes.Ret);
}
typeBuilder.AddInterfaceImplementation(typeof(IComparer<T>));
{
var emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "Compare",
/* attr */
MethodAttributes.Public | MethodAttributes.Virtual,
/* return */
typeof(int),
/* params */
new[] { typeof(T), typeof(T) }
);
var a = emitter.CreateLocal(objectType);
var b = emitter.CreateLocal(objectType);
var v = emitter.CreateLocal(typeof(int));
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(a);
emitter.LoadArgument(2);
emitter.CastAs(objectType);
emitter.StoreLocal(b);
emitter.Load(0);
emitter.StoreLocal(v);
var end = emitter.CreateLabel();
for (var i = 0; i < orders.Length; ++i)
{
if (i > 0)
{
emitter.LoadLocal(v);
emitter.BranchIfTrue(end);
}
var orderInfo = orders[i];
var prop = orderInfo.Property;
var sign = orderInfo.Sign;
emitter.LoadLocal(a);
emitter.Chain(prop);
var couldCompare =
emitter.CompareTo(
sign,
() =>
{
emitter.LoadLocal(b);
emitter.Chain(prop);
}
);
if (!couldCompare)
throw new InvalidOperationException("Property is not comparable.");
emitter.StoreLocal(v);
}
emitter.MarkLabel(end);
emitter.LoadLocal(v);
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IComparer<T>).GetMethod(
"Compare",
new[]
{
typeof(T),
typeof(T)
}
) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}")
);
}
var comparerType = typeBuilder.CreateType();
return (IComparer<T>)ActivatorUtil.CreateInstance(comparerType);
}
}
}

View file

@ -1,80 +1,80 @@
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class DistinctExtension : BaseExtension
{
public static ExtensionInfo ExtInfo =
new ExtensionInfo(30, "Distinct", -1, () => new DistinctExtension());
private IComparer<object> m_Comparer;
private readonly List<Property> m_Properties;
public DistinctExtension() => m_Properties = new List<Property>();
public override ExtensionInfo Info => ExtInfo;
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new Exception("Distinct extension may only be used in combination with an object conditional.");
foreach (Property prop in m_Properties)
{
prop.BindTo(baseType, PropertyAccess.Read);
prop.CheckAccess(from);
}
assembly ??= new AssemblyEmitter("__dynamic");
m_Comparer = DistinctCompiler.Compile<object>(assembly, baseType, m_Properties.ToArray());
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid distinction syntax.");
int end = offset + size;
while (offset < end)
{
string binding = arguments[offset++];
m_Properties.Add(new Property(binding));
}
}
public override void Filter(List<object> list)
{
if (m_Comparer == null)
throw new InvalidOperationException("The extension must first be optimized.");
List<object> copy = new List<object>(list);
copy.Sort(m_Comparer);
list.Clear();
object last = null;
for (int i = 0; i < copy.Count; ++i)
{
object obj = copy[i];
if (last == null || m_Comparer.Compare(obj, last) != 0)
{
list.Add(obj);
last = obj;
}
}
}
}
}
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class DistinctExtension : BaseExtension
{
public static ExtensionInfo ExtInfo =
new ExtensionInfo(30, "Distinct", -1, () => new DistinctExtension());
private readonly List<Property> m_Properties;
private IComparer<object> m_Comparer;
public DistinctExtension() => m_Properties = new List<Property>();
public override ExtensionInfo Info => ExtInfo;
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new Exception("Distinct extension may only be used in combination with an object conditional.");
foreach (var prop in m_Properties)
{
prop.BindTo(baseType, PropertyAccess.Read);
prop.CheckAccess(from);
}
assembly ??= new AssemblyEmitter("__dynamic");
m_Comparer = DistinctCompiler.Compile<object>(assembly, baseType, m_Properties.ToArray());
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid distinction syntax.");
var end = offset + size;
while (offset < end)
{
var binding = arguments[offset++];
m_Properties.Add(new Property(binding));
}
}
public override void Filter(List<object> list)
{
if (m_Comparer == null)
throw new InvalidOperationException("The extension must first be optimized.");
var copy = new List<object>(list);
copy.Sort(m_Comparer);
list.Clear();
object last = null;
for (var i = 0; i < copy.Count; ++i)
{
var obj = copy[i];
if (last == null || m_Comparer.Compare(obj, last) != 0)
{
list.Add(obj);
last = obj;
}
}
}
}
}

View file

@ -1,33 +1,33 @@
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class LimitExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(80, "Limit", 1, () => new LimitExtension());
public override ExtensionInfo Info => ExtInfo;
public int Limit { get; private set; }
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
Limit = Utility.ToInt32(arguments[offset]);
if (Limit < 0)
throw new Exception("Limit cannot be less than zero.");
}
public override void Filter(List<object> list)
{
if (list.Count > Limit)
list.RemoveRange(Limit, list.Count - Limit);
}
}
}
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class LimitExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(80, "Limit", 1, () => new LimitExtension());
public override ExtensionInfo Info => ExtInfo;
public int Limit { get; private set; }
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
Limit = Utility.ToInt32(arguments[offset]);
if (Limit < 0)
throw new Exception("Limit cannot be less than zero.");
}
public override void Filter(List<object> list)
{
if (list.Count > Limit)
list.RemoveRange(Limit, list.Count - Limit);
}
}
}

View file

@ -1,99 +1,99 @@
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class SortExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(40, "Order", -1, () => new SortExtension());
private IComparer<object> m_Comparer;
private readonly List<OrderInfo> m_Orders;
public SortExtension() => m_Orders = new List<OrderInfo>();
public override ExtensionInfo Info => ExtInfo;
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new Exception("The ordering extension may only be used in combination with an object conditional.");
foreach (OrderInfo order in m_Orders)
{
order.Property.BindTo(baseType, PropertyAccess.Read);
order.Property.CheckAccess(from);
}
assembly ??= new AssemblyEmitter("__dynamic");
m_Comparer = SortCompiler.Compile<object>(assembly, baseType, m_Orders.ToArray());
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid ordering syntax.");
if (Insensitive.Equals(arguments[offset], "by"))
{
++offset;
--size;
if (size < 1)
throw new Exception("Invalid ordering syntax.");
}
int end = offset + size;
while (offset < end)
{
string binding = arguments[offset++];
bool isAscending = true;
if (offset < end)
{
string next = arguments[offset];
switch (next.ToLower())
{
case "+":
case "up":
case "asc":
case "ascending":
isAscending = true;
++offset;
break;
case "-":
case "down":
case "desc":
case "descending":
isAscending = false;
++offset;
break;
}
}
Property property = new Property(binding);
m_Orders.Add(new OrderInfo(property, isAscending));
}
}
public override void Filter(List<object> list)
{
if (m_Comparer == null)
throw new InvalidOperationException("The extension must first be optimized.");
list.Sort(m_Comparer);
}
}
}
using System;
using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class SortExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(40, "Order", -1, () => new SortExtension());
private readonly List<OrderInfo> m_Orders;
private IComparer<object> m_Comparer;
public SortExtension() => m_Orders = new List<OrderInfo>();
public override ExtensionInfo Info => ExtInfo;
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new Exception("The ordering extension may only be used in combination with an object conditional.");
foreach (var order in m_Orders)
{
order.Property.BindTo(baseType, PropertyAccess.Read);
order.Property.CheckAccess(from);
}
assembly ??= new AssemblyEmitter("__dynamic");
m_Comparer = SortCompiler.Compile<object>(assembly, baseType, m_Orders.ToArray());
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid ordering syntax.");
if (Insensitive.Equals(arguments[offset], "by"))
{
++offset;
--size;
if (size < 1)
throw new Exception("Invalid ordering syntax.");
}
var end = offset + size;
while (offset < end)
{
var binding = arguments[offset++];
var isAscending = true;
if (offset < end)
{
var next = arguments[offset];
switch (next.ToLower())
{
case "+":
case "up":
case "asc":
case "ascending":
isAscending = true;
++offset;
break;
case "-":
case "down":
case "desc":
case "descending":
isAscending = false;
++offset;
break;
}
}
var property = new Property(binding);
m_Orders.Add(new OrderInfo(property, isAscending));
}
}
public override void Filter(List<object> list)
{
if (m_Comparer == null)
throw new InvalidOperationException("The extension must first be optimized.");
list.Sort(m_Comparer);
}
}
}

View file

@ -1,36 +1,36 @@
using System;
namespace Server.Commands.Generic
{
public sealed class WhereExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(20, "Where", -1, () => new WhereExtension());
public override ExtensionInfo Info => ExtInfo;
public ObjectConditional Conditional { get; private set; }
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new InvalidOperationException("Insanity.");
Conditional.Compile(ref assembly);
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid condition syntax.");
Conditional = ObjectConditional.ParseDirect(from, arguments, offset, size);
}
public override bool IsValid(object obj) => Conditional.CheckCondition(obj);
}
}
using System;
namespace Server.Commands.Generic
{
public sealed class WhereExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(20, "Where", -1, () => new WhereExtension());
public override ExtensionInfo Info => ExtInfo;
public ObjectConditional Conditional { get; private set; }
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new InvalidOperationException("Insanity.");
Conditional.Compile(ref assembly);
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid condition syntax.");
Conditional = ObjectConditional.ParseDirect(from, arguments, offset, size);
}
public override bool IsValid(object obj) => Conditional.CheckCondition(obj);
}
}