168 Commits

650 changed files with 3787 additions and 30748 deletions

1
.gitignore vendored
View File

@@ -68,3 +68,4 @@ crashlytics-build.properties
/UserSettings
/*.zip
*.lnk
/HybridCLRData

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +1,8 @@
fileFormatVersion: 2
guid: 215ebdd4cb9187741a2e24f5e7d8511d
DefaultImporter:
guid: 2e0c61e29fd90f04b9e41265d93e2029
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d815e4d844e6a1c4d849e96e199f8881
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 82867c59112ff5a419fbea2ebff2d3b9
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,90 @@
using System.Collections.Generic;
namespace Cryville.Common.Buffers {
/// <summary>
/// A set of resource pools categorized by a category type.
/// </summary>
/// <typeparam name="TCategory">The category type.</typeparam>
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
public abstract class CategorizedPool<TCategory, TObject> where TObject : class {
/// <summary>
/// The set of underlying pools.
/// </summary>
/// <remarks>
/// <para>The <see cref="Rent(TCategory)" /> and <see cref="Return(TCategory, TObject)" /> method select an underlying pool directly from this set with the category as the key. When overridden, this set must be available since construction.</para>
/// </remarks>
protected abstract IReadOnlyDictionary<TCategory, ObjectPool<TObject>> Buckets { get; }
/// <summary>
/// The count of objects rented from the set of pools.
/// </summary>
public int RentedCount { get; private set; }
/// <summary>
/// Rents an object from the pool.
/// </summary>
/// <param name="category">The category.</param>
/// <returns>The rented object.</returns>
public TObject Rent(TCategory category) {
var obj = Buckets[category].Rent();
RentedCount++;
return obj;
}
/// <summary>
/// Returns a rented object to the pool.
/// </summary>
/// <param name="category">The category.</param>
/// <param name="obj">The object to return.</param>
public void Return(TCategory category, TObject obj) {
Buckets[category].Return(obj);
--RentedCount;
}
}
/// <summary>
/// A utility to access a categorized pool, representing a single unit that uses a shared categorized pool.
/// </summary>
/// <typeparam name="TCategory">The category type.</typeparam>
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
public class CategorizedPoolAccessor<TCategory, TObject> where TObject : class {
readonly CategorizedPool<TCategory, TObject> _pool;
static readonly SimpleObjectPool<Dictionary<TObject, TCategory>> _dictPool
= new SimpleObjectPool<Dictionary<TObject, TCategory>>(1024);
Dictionary<TObject, TCategory> _rented;
/// <summary>
/// Creates an instance of the <see cref="CategorizedPoolAccessor{TCategory, TObject}" /> class.
/// </summary>
/// <param name="pool">The categorized pool.</param>
public CategorizedPoolAccessor(CategorizedPool<TCategory, TObject> pool) {
_pool = pool;
}
/// <summary>
/// Rents an object from the pool.
/// </summary>
/// <param name="category">The category.</param>
/// <returns>The rented object.</returns>
public TObject Rent(TCategory category) {
var obj = _pool.Rent(category);
if (_rented == null) _rented = _dictPool.Rent();
_rented.Add(obj, category);
return obj;
}
/// <summary>
/// Returns a rented object to the pool.
/// </summary>
/// <param name="obj">The object to return.</param>
public void Return(TObject obj) {
_pool.Return(_rented[obj], obj);
_rented.Remove(obj);
}
/// <summary>
/// Returns all objects rented by this accessor to the pool.
/// </summary>
public void ReturnAll() {
if (_rented == null) return;
foreach (var obj in _rented) {
_pool.Return(obj.Value, obj.Key);
}
_rented.Clear();
_dictPool.Return(_rented);
_rented = null;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 4ffe72fef6ebb9e4da3571b4117f0d6d
guid: ec18f22479042d747b88c093aa90c5c0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -14,6 +14,10 @@
_objs = new T[capacity];
}
/// <summary>
/// The count of objects rented from the pool.
/// </summary>
public int RentedCount { get { return _index; } }
/// <summary>
/// Rents a object from the pool.
/// </summary>
/// <returns>The rented object.</returns>
@@ -24,6 +28,7 @@
_objs[_index++] = null;
}
if (obj == null) obj = Construct();
else Reset(obj);
return obj;
}
/// <summary>
@@ -38,5 +43,10 @@
/// </summary>
/// <returns>The new instance.</returns>
protected abstract T Construct();
/// <summary>
/// Resets an object.
/// </summary>
/// <param name="obj">The object.</param>
protected virtual void Reset(T obj) { }
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: dbc046e7cabacbb4fbf74520399a7340
guid: c4ef48e4a4983de4e9c31483df2a918e
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6823ead66b33bc048bbad48719feb25d
guid: 9ec674235c0dd6744af2dab2b58dd53c
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Cryville.Common.Collections.Generic {
public interface IPairList<TKey, TValue> : IList<KeyValuePair<TKey, TValue>> {
void Add(TKey key, TValue value);
void Insert(int index, TKey key, TValue value);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f5b3f3294f679f14f8ec1195b0def630
guid: 73fb17b484b343242bcce27c15ed7d44
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections.Generic {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView<,>))]
public struct PairCollection<TKey, TValue> : IDisposable {
public void Dispose() { }
readonly IPairList<TKey, TValue> _pairList;
readonly IDictionary<TKey, TValue> _dictionary;
public PairCollection(object collection) : this() {
var type = collection.GetType();
if (typeof(IPairList<TKey, TValue>).IsAssignableFrom(type)) _pairList = (IPairList<TKey, TValue>)collection;
else if (typeof(IDictionary<TKey, TValue>).IsAssignableFrom(type)) _dictionary = (IDictionary<TKey, TValue>)collection;
else throw new ArgumentException("Parameter is not a pair collection");
}
public int Count {
get {
if (_pairList != null) return _pairList.Count;
else return _dictionary.Count;
}
}
public void Add(TKey key, TValue value) {
if (_pairList != null) _pairList.Add(key, value);
else _dictionary.Add(key, value);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) {
if (_pairList != null) _pairList.CopyTo(array, index);
else _dictionary.CopyTo(array, index);
}
}
internal class PairCollectionDebugView<TKey, TValue> {
readonly PairCollection<TKey, TValue> _self;
public PairCollectionDebugView(PairCollection<TKey, TValue> self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Items {
get {
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 23377bf2926d93a4b8e3f3ab6040c7f2
guid: 2517e8f040bd36f46948e5fafaf5335c
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections.Generic {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView<,>))]
public class PairList<TKey, TValue> : List<KeyValuePair<TKey, TValue>>, IPairList<TKey, TValue>, IPairList {
public void Add(TKey key, TValue value) {
Add(new KeyValuePair<TKey, TValue>(key, value));
}
public void Add(object key, object value) {
try {
Add((TKey)key, (TValue)value);
}
catch (InvalidCastException) {
throw new ArgumentException("Wrong key type or value type");
}
}
public void Insert(int index, TKey key, TValue value) {
Insert(index, new KeyValuePair<TKey, TValue>(key, value));
}
public void Insert(int index, object key, object value) {
try {
Insert(index, (TKey)key, (TValue)value);
}
catch (InvalidCastException) {
throw new ArgumentException("Wrong key type or value type");
}
}
}
internal class PairListDebugView<TKey, TValue> {
readonly PairList<TKey, TValue> _self;
public PairListDebugView(PairList<TKey, TValue> self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Items {
get {
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: e3c5a8bf05d5e284ba498e91cb0dd35e
guid: d9ed5ea8b7b1a934287e7ec5971166c0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,8 @@
using System.Collections;
namespace Cryville.Common.Collections {
public interface IPairList : IList {
void Add(object key, object value);
void Insert(int index, object key, object value);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 046617672d437de4ab7e644a55defd3b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView))]
public struct PairCollection : IDisposable {
public void Dispose() { }
readonly IPairList _pairList;
readonly IDictionary _dictionary;
public PairCollection(object collection) : this() {
var type = collection.GetType();
if (typeof(IPairList).IsAssignableFrom(type)) _pairList = (IPairList)collection;
else if (typeof(IDictionary).IsAssignableFrom(type)) _dictionary = (IDictionary)collection;
else throw new ArgumentException("Parameter is not a pair collection");
}
public int Count {
get {
if (_pairList != null) return _pairList.Count;
else return _dictionary.Count;
}
}
public void Add(object key, object value) {
if (_pairList != null) _pairList.Add(key, value);
else _dictionary.Add(key, value);
}
public void CopyTo(KeyValuePair<object, object>[] array, int index) {
if (_pairList != null) _pairList.CopyTo(array, index);
else _dictionary.CopyTo(array, index);
}
}
internal class PairCollectionDebugView {
readonly PairCollection _self;
public PairCollectionDebugView(PairCollection self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<object, object>[] Items {
get {
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f87dfb8f6a1f5640b6deae741cd715c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView))]
public class PairList : List<KeyValuePair<object, object>>, IPairList {
public void Add(object key, object value) {
Add(new KeyValuePair<object, object>(key, value));
}
public void Insert(int index, object key, object value) {
Insert(index, new KeyValuePair<object, object>(key, value));
}
}
internal class PairListDebugView {
readonly PairList _self;
public PairListDebugView(PairList self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<object, object>[] Items {
get {
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57fc9f037c1fda5449e2a365a835c82c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -3,7 +3,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Cryville.Common.Font {
public abstract class FontFile : IEnumerable<Typeface> {

View File

@@ -45,7 +45,7 @@ namespace Cryville.Common.Font {
return tableDirectoryOffsets;
}
public override TableDirectory GetSubTable(UInt32 item) {
var i = (UInt32)item;
var i = item;
return new TableDirectory(Reader, i);
}
}

View File

@@ -2,6 +2,7 @@
namespace Cryville.Common {
public struct Identifier : IEquatable<Identifier> {
public static Identifier Empty = new Identifier(0);
public int Key { get; private set; }
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
public Identifier(int key) {
@@ -24,11 +25,11 @@ namespace Cryville.Common {
if (Key == 0) return "";
return Name.ToString();
}
public static implicit operator Identifier(string identifier) {
return new Identifier(identifier);
public static bool operator ==(Identifier lhs, Identifier rhs) {
return lhs.Equals(rhs);
}
public static implicit operator string(Identifier identifier) {
return identifier.ToString();
public static bool operator !=(Identifier lhs, Identifier rhs) {
return !lhs.Equals(rhs);
}
}
}

View File

@@ -54,16 +54,13 @@ namespace Cryville.Common.Math {
return res;
}
/// <summary>
/// Creates a <see cref="System.Single" /> column vector and fills it with polynomial coefficients.
/// Fills a <see cref="System.Single" /> column vector with polynomial coefficients.
/// </summary>
/// <param name="size">The size of the column vector.</param>
/// <param name="vec">The column vector.</param>
/// <param name="num">The base number.</param>
/// <returns>A <see cref="System.Single" /> column vector filled with polynomial coefficients.</returns>
public static ColumnVector<float> WithPolynomialCoefficients(int size, float num) {
var m = new ColumnVector<float>(size);
for (var i = 0; i < size; i++)
m[i] = (float)System.Math.Pow(num, i);
return m;
public static void FillWithPolynomialCoefficients(ColumnVector<float> vec, float num) {
for (var i = 0; i < vec.Size; i++)
vec[i] = (float)System.Math.Pow(num, i);
}
}
}

View File

@@ -0,0 +1,44 @@
using SMath = System.Math;
namespace Cryville.Common.Math {
// Ported from https://github.com/arian/cubic-bezier/blob/master/index.js
public static class CubicBezier {
public static float Evaluate(float t, float x1, float y1, float x2, float y2, float epsilon) {
float x = t, t0, t1, t2, tx, d2, i;
for (t2 = x, i = 0; i < 8; i++) {
tx = CurveX(t2, x1, x2) - x;
if (SMath.Abs(tx) < epsilon) return CurveY(t2, y1, y2);
d2 = DerivativeCurveX(t2, x1, x2);
if (SMath.Abs(d2) < 1e-6) break;
t2 -= tx / d2;
}
t0 = 0; t1 = 1; t2 = x;
if (t2 < t0) return CurveY(t0, y1, y2);
if (t2 > t1) return CurveY(t1, y1, y2);
while (t0 < t1) {
tx = CurveX(t2, x1, x2);
if (SMath.Abs(tx - x) < epsilon) return CurveY(t2, y1, y2);
if (x > tx) t0 = t2;
else t1 = t2;
t2 = (t1 - t0) * .5f + t0;
}
return CurveY(t2, y1, y2);
}
static float CurveX(float t, float x1, float x2) {
float v = 1 - t;
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
}
static float CurveY(float t, float y1, float y2) {
float v = 1 - t;
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
}
static float DerivativeCurveX(float t, float x1, float x2) {
float v = 1 - t;
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (-t * t * t + 2 * v * t) * x2;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17dd6f775fc965f43960da7166b55b87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,12 +12,12 @@ namespace Cryville.Common.Math {
/// <param name="error">The error.</param>
/// <param name="n">The numerator.</param>
/// <param name="d">The denominator.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="value" /> is less than 0 or <paramref name="error" /> is not greater than 0 or not less than 1.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="value" /> is less than 0 or <paramref name="error" /> is not greater than 0 or greater than 1.</exception>
public static void ToFraction(double value, double error, out int n, out int d) {
if (value < 0.0)
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
if (error <= 0.0 || error >= 1.0)
throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
if (error <= 0.0 || error > 1.0)
throw new ArgumentOutOfRangeException("error", "Must be > 0 and <= 1.");
int num = (int)System.Math.Floor(value);
value -= num;

View File

@@ -1,4 +1,4 @@
using System;
using UnsafeIL;
namespace Cryville.Common.Math {
/// <summary>
@@ -40,11 +40,11 @@ namespace Cryville.Common.Math {
/// </summary>
/// <typeparam name="T">The vector type.</typeparam>
/// <param name="v">The column vector.</param>
/// <param name="result">The result column vector.</param>
/// <param name="o">The column operator.</param>
/// <returns>The column vector eliminated.</returns>
public ColumnVector<T> Eliminate<T>(ColumnVector<T> v, IVectorOperator<T> o) {
public void Eliminate<T>(ColumnVector<T> v, ColumnVector<T> result, IVectorOperator<T> o) {
int s = Size;
Array.Copy(content, buffer, Size * Size);
FillBuffer();
for (int i = 0; i < s; i++) refl[i] = i;
for (int r = 0; r < s; r++) {
for (int r0 = r; r0 < s; r0++)
@@ -66,14 +66,17 @@ namespace Cryville.Common.Math {
v[or1] = o.Add(v[or1], o.ScalarMultiply(-sf1, v[or]));
}
}
ColumnVector<T> res = new ColumnVector<T>(s);
for (int r2 = s - 1; r2 >= 0; r2--) {
var v2 = v[refl[r2]];
for (int c2 = r2 + 1; c2 < s; c2++)
v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], res[refl[c2]]));
res[refl[r2]] = v2;
v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], result[refl[c2]]));
result[refl[r2]] = v2;
}
}
unsafe void FillBuffer() {
fixed (void* ptrc = content, ptrb = buffer) {
Unsafe.CopyBlock(ptrb, ptrc, (uint)(Size * Size * sizeof(float)));
}
return res;
}
/// <summary>
/// Creates a square matrix and fills it with polynomial coefficients.

View File

@@ -1,7 +1,21 @@
using System;
namespace Cryville.Common.Pdt {
/// <summary>
/// Indicates that the attributed member is an element list.
/// </summary>
/// <remarks>
/// <para>An element list is a <see cref="System.Collections.IDictionary" /> or <see cref="Cryville.Common.Collections.Generic.IPairList" /> that represents a collection of PDT elements. There must be at most one element list in a class.</para>
/// </remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ElementListAttribute : Attribute { }
public class ComponentListAttribute : Attribute { }
/// <summary>
/// Indicates that the attributed member is a property list.
/// </summary>
/// <remarks>
/// <para>A property list is a <see cref="System.Collections.IDictionary" /> or <see cref="Cryville.Common.Collections.Generic.IPairList" /> that represents a collection of PDT properties. There must be at most one property list in a class.</para>
/// </remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class PropertyListAttribute : Attribute { }
}

View File

@@ -186,7 +186,7 @@ namespace Cryville.Common.Pdt {
protected abstract PdtOperator GetOperator(PdtOperatorSignature sig);
unsafe void Operate(PdtOperator op, int pc, bool noset = false) {
fixed (byte* pmem = _mem) {
op.Begin(this);
op.Begin(this, pc);
for (int i = 0; i < pc; i++) {
var frame = _stack[--_framecount];
op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length));

View File

@@ -11,7 +11,7 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// Whether the value of this expression is constant.
/// </summary>
/// <remarks>The value of this property is <c>false</c> until it is optimized.</remarks>
/// <remarks>The value of this property is <see langword="false" /> until it is optimized.</remarks>
public bool IsConstant { get; internal set; }
internal bool IsPotentialConstant;
internal PdtExpression(LinkedList<PdtInstruction> ins) {
@@ -92,7 +92,7 @@ namespace Cryville.Common.Pdt {
}
}
public partial class PdtInterpreter {
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
static readonly Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
{ '@', 7 },
{ '*', 6 }, { '/', 6 }, { '%', 6 },
{ '+', 5 }, { '-', 5 },
@@ -103,7 +103,7 @@ namespace Cryville.Common.Pdt {
{ ',', 0 },
{ '$', -1 },
};
readonly static Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
static readonly Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
{ '@', 0 },
{ '*', 0 }, { '/', 0 }, { '%', 0 },
{ '+', 0 }, { '-', 0 },
@@ -115,7 +115,7 @@ namespace Cryville.Common.Pdt {
{ '$', -1 },
};
readonly static PdtExpression _emptyexp;
static readonly PdtExpression _emptyexp;
static PdtInterpreter() {
var ins = new LinkedList<PdtInstruction>();
ins.AddLast(new PdtInstruction.PushConstant(
@@ -143,7 +143,7 @@ namespace Cryville.Common.Pdt {
public override string ToString() {
return string.Format("0x{0:x4}: {1}", Type, Value);
}
public readonly static PdtExpToken EmptyOperator = new PdtExpToken {
public static readonly PdtExpToken EmptyOperator = new PdtExpToken {
Type = 0x0080,
Value = "$",
};

View File

@@ -6,30 +6,30 @@
/// <summary>
/// Error type.
/// </summary>
public readonly static int Error = 0x00525245;
public const int Error = 0x00525245;
/// <summary>
/// Array of a same variable-length type, with a suffix indicating the element count and the element type.
/// </summary>
public readonly static int Array = 0x00525241;
public const int Array = 0x00525241;
/// <summary>
/// Null type.
/// </summary>
public readonly static int Null = 0x4c4c554e;
public const int Null = 0x4c4c554e;
/// <summary>
/// IEEE 754 32-bit floating-point number.
/// </summary>
public readonly static int Number = 0x004d554e;
public const int Number = 0x004d554e;
/// <summary>
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
/// </summary>
public readonly static int String = 0x00525453;
public const int String = 0x00525453;
/// <summary>
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units, representing the name of an undefined variable.
/// </summary>
public readonly static int Undefined = 0x00444e55;
public const int Undefined = 0x00444e55;
/// <summary>
/// Vector of a same constant-length type, with a suffix indicating the element type.
/// </summary>
public readonly static int Vector = 0x00434556;
public const int Vector = 0x00434556;
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Cryville.Common.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -27,16 +28,16 @@ namespace Cryville.Common.Pdt {
/// <item><term><c>0x1000</c></term><description>End of Key</description></item>
/// </list>
/// </remarks>
readonly static int[] cm = new int[] {
static readonly int[] cm = new int[] {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0001, 0x0080, 0x0100, 0x0000, 0x0030, 0x0080, 0x0080, 0x0000, 0x0200, 0x0400, 0x0080, 0x0080, 0x0080, 0x0080, 0x0040, 0x0080,
0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x1000, 0x1800, 0x0080, 0x0080, 0x0080, 0x0030,
0x0080, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, 0x0000, 0x0000, 0x0030,
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0080, 0x0000, 0x0080, 0x0030,
0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x1000, 0x0080, 0x1000, 0x0000, 0x0000,
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x1000, 0x0080, 0x1000, 0x0080, 0x0000,
};
/// <summary>
@@ -54,43 +55,92 @@ namespace Cryville.Common.Pdt {
/// <param name="binder">The binder.</param>
/// <returns>The interpreted object.</returns>
public static T Interpret<T>(string src, Binder binder) {
return (T)new PdtInterpreter(src, typeof(T), binder).Interpret();
return (T)new PdtInterpreter(src, binder).Interpret(typeof(T));
}
/// <summary>
/// The source string.
/// </summary>
public string Source { get; private set; }
readonly Type _type;
readonly Binder _binder;
Binder _binder;
/// <summary>
/// The current position in the string being parsed by the interpreter.
/// </summary>
public int Position { get; private set; }
#pragma warning disable IDE1006
/// <summary>
/// The character at the current position.
/// </summary>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected char cc { get { return Source[Position]; } }
/// <summary>
/// The category of the character.
/// </summary>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected int ct { get { return cm[cc]; } }
protected string tokenb(int flag) { // Token Whitelist
/// <summary>
/// Reads a token until a character of type <paramref name="flag" /> is met.
/// </summary>
/// <param name="flag">The type filter.</param>
/// <returns>A token from the current position (inclusive) to the next character of type <paramref name="flag" /> (exclusive).</returns>
/// <exception cref="IndexOutOfRangeException">No character of type <paramref name="flag" /> is met.</exception>
protected string tokenb(int flag) {
int sp = Position;
while ((ct & flag) == 0) Position++;
return Source.Substring(sp, Position - sp);
}
protected string tokenw(int flag) { // Token Whitelist
/// <summary>
/// Reads a token until a character that is not of type <paramref name="flag" /> is met.
/// </summary>
/// <param name="flag">The type filter.</param>
/// <returns>A token from the current position (inclusive) to the next character that is not of type <paramref name="flag" /> (exclusive).</returns>
/// <exception cref="IndexOutOfRangeException">No character that is not of type <paramref name="flag" /> is met.</exception>
protected string tokenw(int flag) {
int sp = Position;
while ((ct & flag) != 0) Position++;
return Source.Substring(sp, Position - sp);
}
/// <summary>
/// Skips over whitespaces.
/// </summary>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected void ws() {
while ((ct & 0x0001) != 0) Position++;
}
#pragma warning restore IDE1006
/// <summary>
/// Reads the current character and increments the position.
/// </summary>
/// <returns>The current character.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected char GetChar() {
char r = cc;
Position++;
return r;
}
/// <summary>
/// Reads an identifier.
/// </summary>
/// <returns>An identifier.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected string GetIdentifier() {
if ((ct & 0x0020) == 0) return "";
return tokenw(0x0010);
}
/// <summary>
/// Reads a number.
/// </summary>
/// <returns>A number.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected string GetNumber() {
return tokenw(0x0040);
}
/// <summary>
/// Reads a string.
/// </summary>
/// <returns>A string.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected string GetString() {
int sp = Position;
do {
@@ -100,6 +150,11 @@ namespace Cryville.Common.Pdt {
Position++;
return Regex.Replace(Source.Substring(sp + 1, Position - sp - 2), @"\\(.)", "$1");
}
/// <summary>
/// Reads an expression.
/// </summary>
/// <returns>An expression.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
protected PdtExpression GetExp() {
var ins = new LinkedList<PdtInstruction>();
int _;
@@ -112,23 +167,27 @@ namespace Cryville.Common.Pdt {
/// Creates an instance of the <see cref="PdtInterpreter" /> class.
/// </summary>
/// <param name="src">The source string.</param>
/// <param name="type">The destination type.</param>
/// <param name="binder">The binder. May be <c>null</c>.</param>
public PdtInterpreter(string src, Type type, Binder binder) {
public PdtInterpreter(string src, Binder binder) {
Source = src;
_type = type;
_binder = binder;
if (_binder == null)
_binder = BinderAttribute.CreateBinderOfType(_type);
}
int[] m_formatVersion;
public int[] GetFormatVersion() {
if (m_formatVersion == null) InterpretDirectives();
return m_formatVersion;
}
/// <summary>
/// Interprets the source to an object.
/// </summary>
/// <param name="type">The output type.</param>
/// <returns>The interpreted object.</returns>
public object Interpret() {
public object Interpret(Type type) {
try {
InterpretDirectives();
return InterpretObject(_type);
if (m_formatVersion == null) InterpretDirectives();
if (_binder == null)
_binder = BinderAttribute.CreateBinderOfType(type);
return InterpretObject(type);
}
catch (Exception ex) {
throw new PdtParsingException(this, ex);
@@ -146,7 +205,10 @@ namespace Cryville.Common.Pdt {
break;
case "format":
ws();
if (GetNumber() != "1")
m_formatVersion = (from i in GetNumber().Split('.') select int.Parse(i)).ToArray();
if (m_formatVersion.Length == 0)
throw new FormatException("Invalid format version");
if (m_formatVersion[0] != 1)
throw new NotSupportedException("Format not supported");
flag = true;
break;
@@ -167,10 +229,14 @@ namespace Cryville.Common.Pdt {
}
object InterpretObject(Type type) {
var result = ReflectionHelper.InvokeEmptyConstructor(type);
bool dictflag = ReflectionHelper.IsGenericDictionary(type);
bool dictflag = typeof(IDictionary).IsAssignableFrom(type);
while (true) {
try { ws(); }
catch (IndexOutOfRangeException) { return result; }
if (cc == '}') {
GetChar();
return result;
}
object pkey = InterpretKey(type);
char c = GetChar();
switch (c) {
@@ -183,19 +249,20 @@ namespace Cryville.Common.Pdt {
((IDictionary)result).Add(key, value);
}
else {
MemberInfo prop;
bool flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop);
if (!flag && pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
MemberInfo prop = null;
bool flag = false;
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop);
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
Type ptype = ReflectionHelper.GetMemberType(prop);
if (ReflectionHelper.IsGenericDictionary(ptype)) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
if (flag) {
if (flag) {
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(vtype);
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
collection.Add(key, value);
}
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
}
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
}
@@ -211,28 +278,36 @@ namespace Cryville.Common.Pdt {
((IDictionary)result).Add(key, value);
}
else {
MemberInfo prop;
bool flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop);
if (!flag && pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
MemberInfo prop = null;
bool flag = false;
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop);
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
var ptype = ReflectionHelper.GetMemberType(prop);
if (!typeof(IDictionary).IsAssignableFrom(ptype)) {
if (flag) {
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
collection.Add(key, value);
}
}
else {
object value = _binder.ChangeType(exp, ptype, null);
ReflectionHelper.SetValue(prop, result, value, _binder);
}
else {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
}
}
break;
case '}':
return result;
default:
throw new InvalidOperationException("Internal error: Invalid key interpretation");
}
}
}
/// <summary>
/// Interprets a key from the current position.
/// </summary>
/// <returns>The interpreted key.</returns>
protected virtual object InterpretKey(Type type) {
return tokenb(0x1000).Trim();
}

View File

@@ -4,14 +4,14 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// PDT operator.
/// </summary>
public unsafe abstract class PdtOperator {
public abstract unsafe class PdtOperator {
byte* _prmem;
int _loadindex;
readonly PdtVariableMemory[] _operands;
/// <summary>
/// The count of the operands loaded.
/// </summary>
protected int LoadedOperandCount { get { return ParamCount - _loadindex; } }
protected int LoadedOperandCount { get; private set; }
/// <summary>
/// Gets the operand at the specified index.
/// </summary>
@@ -24,24 +24,24 @@ namespace Cryville.Common.Pdt {
int i = index + _loadindex;
return _operands[i];
}
internal int ParamCount { get; private set; }
readonly int _pc;
/// <summary>
/// Creates an instance of the <see cref="PdtOperator" /> class.
/// </summary>
/// <param name="pc">The suggested parameter count.</param>
protected PdtOperator(int pc) {
ParamCount = pc;
_pc = pc;
_operands = new PdtVariableMemory[pc];
}
PdtEvaluatorBase _etor;
bool _rfreq = true;
internal void Begin(PdtEvaluatorBase etor) {
internal void Begin(PdtEvaluatorBase etor, int pc) {
_etor = etor;
_loadindex = ParamCount;
_loadindex = LoadedOperandCount = pc;
}
internal void LoadOperand(PdtVariableMemory mem) {
if (_loadindex == 0) return;
_operands[--_loadindex] = mem;
if (--_loadindex >= _pc) return;
_operands[_loadindex] = mem;
}
internal void Call(byte* prmem, bool noset) {
_prmem = prmem;
@@ -55,6 +55,9 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// Executes the operator.
/// </summary>
/// <remarks>
/// <para>When overridden, this method reads operands by calling <see cref="GetOperand(int)" />, and writes the result to the frame obtained by calling <see cref="GetReturnFrame(int, int)" />.</para>
/// </remarks>
protected abstract void Execute();
/// <summary>
/// Gets a return frame.

View File

@@ -1,4 +1,5 @@
using System;
using UnsafeIL;
namespace Cryville.Common.Pdt {
/// <summary>
@@ -42,7 +43,9 @@ namespace Cryville.Common.Pdt {
/// <param name="dest">The destination buffer.</param>
/// <param name="destOffset">The offset on the destination buffer to start copying to.</param>
/// <param name="length">The length to copy.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="length" /> is greater than the length of the span.</exception>
public void CopyTo(byte* dest, int destOffset, int length) {
if (length > Length) throw new ArgumentOutOfRangeException("length");
for (int i = 0; i < length; i++)
dest[destOffset + i] = _ptr[i];
}
@@ -126,10 +129,43 @@ namespace Cryville.Common.Pdt {
throw new InvalidCastException("Not an identifier");
return *(int*)(_ptr + offset);
}
internal void* TrustedAsOfLength(int len) {
if (Length < len)
throw new InvalidCastException("Type not matched");
return _ptr;
/// <summary>
/// Gets the memory of the span as an instance of the specified type.
/// </summary>
/// <typeparam name="T">The specified type.</typeparam>
/// <param name="offset">The offset on the span to start reading from.</param>
/// <returns>An instance of the specified type.</returns>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="offset" /> is not less than the length of the span.</exception>
/// <exception cref="InvalidCastException">The length of the span is not sufficient.</exception>
/// <remarks>
/// <para>Use <see cref="AsNumber(int)" /> instead while reading an unaligned number.</para>
/// </remarks>
public T As<T>(int offset = 0) {
var len = Unsafe.SizeOf<T>();
if (offset >= Length)
throw new ArgumentOutOfRangeException("offset");
if (offset + len > Length)
throw new InvalidCastException("Frame length not sufficient");
return Unsafe.Read<T>(_ptr + offset);
}
/// <summary>
/// Sets the memory of the span to an instance of the specified type.
/// </summary>
/// <typeparam name="T">The specified type.</typeparam>
/// <param name="value">The value.</param>
/// <param name="offset">The offset from the start of the span.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="offset" /> is not less than the length of the span.</exception>
/// <exception cref="InvalidCastException">The length of the span is not sufficient.</exception>
/// <remarks>
/// <para>Use <see cref="SetNumber(float, int)" /> instead while writing an unaligned number.</para>
/// </remarks>
public void Set<T>(T value, int offset = 0) {
var len = Unsafe.SizeOf<T>();
if (offset >= Length)
throw new ArgumentOutOfRangeException("offset");
if (offset + len > Length)
throw new InvalidCastException("Frame length not sufficient");
Unsafe.Write(_ptr + offset, value);
}
/// <summary>
/// Gets the array suffix.

View File

@@ -28,8 +28,8 @@ namespace Cryville.Common.Unity {
set { m_filter = value; }
}
public Dictionary<string, string> m_presetPaths = new Dictionary<string, string>();
public Dictionary<string, string> PresetPaths {
public IReadOnlyDictionary<string, string> m_presetPaths = new Dictionary<string, string>();
public IReadOnlyDictionary<string, string> PresetPaths {
get { return m_presetPaths; }
set { m_presetPaths = value; }
}

Some files were not shown because too many files have changed in this diff Show More