168 Commits

650 changed files with 3787 additions and 30748 deletions

1
.gitignore vendored
View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 215ebdd4cb9187741a2e24f5e7d8511d guid: 2e0c61e29fd90f04b9e41265d93e2029
DefaultImporter: NativeFormatImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 7400000
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: 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 fileFormatVersion: 2
guid: 4ffe72fef6ebb9e4da3571b4117f0d6d guid: ec18f22479042d747b88c093aa90c5c0
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@@ -14,6 +14,10 @@
_objs = new T[capacity]; _objs = new T[capacity];
} }
/// <summary> /// <summary>
/// The count of objects rented from the pool.
/// </summary>
public int RentedCount { get { return _index; } }
/// <summary>
/// Rents a object from the pool. /// Rents a object from the pool.
/// </summary> /// </summary>
/// <returns>The rented object.</returns> /// <returns>The rented object.</returns>
@@ -24,6 +28,7 @@
_objs[_index++] = null; _objs[_index++] = null;
} }
if (obj == null) obj = Construct(); if (obj == null) obj = Construct();
else Reset(obj);
return obj; return obj;
} }
/// <summary> /// <summary>
@@ -38,5 +43,10 @@
/// </summary> /// </summary>
/// <returns>The new instance.</returns> /// <returns>The new instance.</returns>
protected abstract T Construct(); 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 fileFormatVersion: 2
guid: dbc046e7cabacbb4fbf74520399a7340 guid: c4ef48e4a4983de4e9c31483df2a918e
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 6823ead66b33bc048bbad48719feb25d guid: 9ec674235c0dd6744af2dab2b58dd53c
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} 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 fileFormatVersion: 2
guid: f5b3f3294f679f14f8ec1195b0def630 guid: 73fb17b484b343242bcce27c15ed7d44
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 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 fileFormatVersion: 2
guid: 23377bf2926d93a4b8e3f3ab6040c7f2 guid: 2517e8f040bd36f46948e5fafaf5335c
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 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 fileFormatVersion: 2
guid: e3c5a8bf05d5e284ba498e91cb0dd35e guid: d9ed5ea8b7b1a934287e7ec5971166c0
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
namespace Cryville.Common.Font { namespace Cryville.Common.Font {
public abstract class FontFile : IEnumerable<Typeface> { public abstract class FontFile : IEnumerable<Typeface> {

View File

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

View File

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

View File

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

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="error">The error.</param>
/// <param name="n">The numerator.</param> /// <param name="n">The numerator.</param>
/// <param name="d">The denominator.</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) { public static void ToFraction(double value, double error, out int n, out int d) {
if (value < 0.0) if (value < 0.0)
throw new ArgumentOutOfRangeException("value", "Must be >= 0."); throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
if (error <= 0.0 || error >= 1.0) if (error <= 0.0 || error > 1.0)
throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1."); throw new ArgumentOutOfRangeException("error", "Must be > 0 and <= 1.");
int num = (int)System.Math.Floor(value); int num = (int)System.Math.Floor(value);
value -= num; value -= num;

View File

@@ -1,4 +1,4 @@
using System; using UnsafeIL;
namespace Cryville.Common.Math { namespace Cryville.Common.Math {
/// <summary> /// <summary>
@@ -40,11 +40,11 @@ namespace Cryville.Common.Math {
/// </summary> /// </summary>
/// <typeparam name="T">The vector type.</typeparam> /// <typeparam name="T">The vector type.</typeparam>
/// <param name="v">The column vector.</param> /// <param name="v">The column vector.</param>
/// <param name="result">The result column vector.</param>
/// <param name="o">The column operator.</param> /// <param name="o">The column operator.</param>
/// <returns>The column vector eliminated.</returns> public void Eliminate<T>(ColumnVector<T> v, ColumnVector<T> result, IVectorOperator<T> o) {
public ColumnVector<T> Eliminate<T>(ColumnVector<T> v, IVectorOperator<T> o) {
int s = Size; int s = Size;
Array.Copy(content, buffer, Size * Size); FillBuffer();
for (int i = 0; i < s; i++) refl[i] = i; for (int i = 0; i < s; i++) refl[i] = i;
for (int r = 0; r < s; r++) { for (int r = 0; r < s; r++) {
for (int r0 = r; r0 < s; r0++) 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])); 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--) { for (int r2 = s - 1; r2 >= 0; r2--) {
var v2 = v[refl[r2]]; var v2 = v[refl[r2]];
for (int c2 = r2 + 1; c2 < s; c2++) for (int c2 = r2 + 1; c2 < s; c2++)
v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], res[refl[c2]])); v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], result[refl[c2]]));
res[refl[r2]] = v2; 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> /// <summary>
/// Creates a square matrix and fills it with polynomial coefficients. /// Creates a square matrix and fills it with polynomial coefficients.

View File

@@ -1,7 +1,21 @@
using System; using System;
namespace Cryville.Common.Pdt { 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 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 { } public class PropertyListAttribute : Attribute { }
} }

View File

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

View File

@@ -11,7 +11,7 @@ namespace Cryville.Common.Pdt {
/// <summary> /// <summary>
/// Whether the value of this expression is constant. /// Whether the value of this expression is constant.
/// </summary> /// </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; } public bool IsConstant { get; internal set; }
internal bool IsPotentialConstant; internal bool IsPotentialConstant;
internal PdtExpression(LinkedList<PdtInstruction> ins) { internal PdtExpression(LinkedList<PdtInstruction> ins) {
@@ -92,7 +92,7 @@ namespace Cryville.Common.Pdt {
} }
} }
public partial class PdtInterpreter { 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 }, { '@', 7 },
{ '*', 6 }, { '/', 6 }, { '%', 6 }, { '*', 6 }, { '/', 6 }, { '%', 6 },
{ '+', 5 }, { '-', 5 }, { '+', 5 }, { '-', 5 },
@@ -103,7 +103,7 @@ namespace Cryville.Common.Pdt {
{ ',', 0 }, { ',', 0 },
{ '$', -1 }, { '$', -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 }, { '/', 0 }, { '%', 0 },
{ '+', 0 }, { '-', 0 }, { '+', 0 }, { '-', 0 },
@@ -115,7 +115,7 @@ namespace Cryville.Common.Pdt {
{ '$', -1 }, { '$', -1 },
}; };
readonly static PdtExpression _emptyexp; static readonly PdtExpression _emptyexp;
static PdtInterpreter() { static PdtInterpreter() {
var ins = new LinkedList<PdtInstruction>(); var ins = new LinkedList<PdtInstruction>();
ins.AddLast(new PdtInstruction.PushConstant( ins.AddLast(new PdtInstruction.PushConstant(
@@ -143,7 +143,7 @@ namespace Cryville.Common.Pdt {
public override string ToString() { public override string ToString() {
return string.Format("0x{0:x4}: {1}", Type, Value); 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, Type = 0x0080,
Value = "$", Value = "$",
}; };

View File

@@ -6,30 +6,30 @@
/// <summary> /// <summary>
/// Error type. /// Error type.
/// </summary> /// </summary>
public readonly static int Error = 0x00525245; public const int Error = 0x00525245;
/// <summary> /// <summary>
/// Array of a same variable-length type, with a suffix indicating the element count and the element type. /// Array of a same variable-length type, with a suffix indicating the element count and the element type.
/// </summary> /// </summary>
public readonly static int Array = 0x00525241; public const int Array = 0x00525241;
/// <summary> /// <summary>
/// Null type. /// Null type.
/// </summary> /// </summary>
public readonly static int Null = 0x4c4c554e; public const int Null = 0x4c4c554e;
/// <summary> /// <summary>
/// IEEE 754 32-bit floating-point number. /// IEEE 754 32-bit floating-point number.
/// </summary> /// </summary>
public readonly static int Number = 0x004d554e; public const int Number = 0x004d554e;
/// <summary> /// <summary>
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units. /// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
/// </summary> /// </summary>
public readonly static int String = 0x00525453; public const int String = 0x00525453;
/// <summary> /// <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. /// 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> /// </summary>
public readonly static int Undefined = 0x00444e55; public const int Undefined = 0x00444e55;
/// <summary> /// <summary>
/// Vector of a same constant-length type, with a suffix indicating the element type. /// Vector of a same constant-length type, with a suffix indicating the element type.
/// </summary> /// </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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -27,16 +28,16 @@ namespace Cryville.Common.Pdt {
/// <item><term><c>0x1000</c></term><description>End of Key</description></item> /// <item><term><c>0x1000</c></term><description>End of Key</description></item>
/// </list> /// </list>
/// </remarks> /// </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 // 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, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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, 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, 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, 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, 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> /// <summary>
@@ -54,43 +55,92 @@ namespace Cryville.Common.Pdt {
/// <param name="binder">The binder.</param> /// <param name="binder">The binder.</param>
/// <returns>The interpreted object.</returns> /// <returns>The interpreted object.</returns>
public static T Interpret<T>(string src, Binder binder) { 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; } public string Source { get; private set; }
readonly Type _type; Binder _binder;
readonly Binder _binder; /// <summary>
/// The current position in the string being parsed by the interpreter.
/// </summary>
public int Position { get; private set; } public int Position { get; private set; }
#pragma warning disable IDE1006 #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]; } } 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 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; int sp = Position;
while ((ct & flag) == 0) Position++; while ((ct & flag) == 0) Position++;
return Source.Substring(sp, Position - sp); 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; int sp = Position;
while ((ct & flag) != 0) Position++; while ((ct & flag) != 0) Position++;
return Source.Substring(sp, Position - sp); 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() { protected void ws() {
while ((ct & 0x0001) != 0) Position++; while ((ct & 0x0001) != 0) Position++;
} }
#pragma warning restore IDE1006 #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() { protected char GetChar() {
char r = cc; char r = cc;
Position++; Position++;
return r; 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() { protected string GetIdentifier() {
if ((ct & 0x0020) == 0) return ""; if ((ct & 0x0020) == 0) return "";
return tokenw(0x0010); 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() { protected string GetNumber() {
return tokenw(0x0040); 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() { protected string GetString() {
int sp = Position; int sp = Position;
do { do {
@@ -100,6 +150,11 @@ namespace Cryville.Common.Pdt {
Position++; Position++;
return Regex.Replace(Source.Substring(sp + 1, Position - sp - 2), @"\\(.)", "$1"); 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() { protected PdtExpression GetExp() {
var ins = new LinkedList<PdtInstruction>(); var ins = new LinkedList<PdtInstruction>();
int _; int _;
@@ -112,23 +167,27 @@ namespace Cryville.Common.Pdt {
/// Creates an instance of the <see cref="PdtInterpreter" /> class. /// Creates an instance of the <see cref="PdtInterpreter" /> class.
/// </summary> /// </summary>
/// <param name="src">The source string.</param> /// <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> /// <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; Source = src;
_type = type;
_binder = binder; _binder = binder;
if (_binder == null) }
_binder = BinderAttribute.CreateBinderOfType(_type); int[] m_formatVersion;
public int[] GetFormatVersion() {
if (m_formatVersion == null) InterpretDirectives();
return m_formatVersion;
} }
/// <summary> /// <summary>
/// Interprets the source to an object. /// Interprets the source to an object.
/// </summary> /// </summary>
/// <param name="type">The output type.</param>
/// <returns>The interpreted object.</returns> /// <returns>The interpreted object.</returns>
public object Interpret() { public object Interpret(Type type) {
try { try {
InterpretDirectives(); if (m_formatVersion == null) InterpretDirectives();
return InterpretObject(_type); if (_binder == null)
_binder = BinderAttribute.CreateBinderOfType(type);
return InterpretObject(type);
} }
catch (Exception ex) { catch (Exception ex) {
throw new PdtParsingException(this, ex); throw new PdtParsingException(this, ex);
@@ -146,7 +205,10 @@ namespace Cryville.Common.Pdt {
break; break;
case "format": case "format":
ws(); 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"); throw new NotSupportedException("Format not supported");
flag = true; flag = true;
break; break;
@@ -167,10 +229,14 @@ namespace Cryville.Common.Pdt {
} }
object InterpretObject(Type type) { object InterpretObject(Type type) {
var result = ReflectionHelper.InvokeEmptyConstructor(type); var result = ReflectionHelper.InvokeEmptyConstructor(type);
bool dictflag = ReflectionHelper.IsGenericDictionary(type); bool dictflag = typeof(IDictionary).IsAssignableFrom(type);
while (true) { while (true) {
try { ws(); } try { ws(); }
catch (IndexOutOfRangeException) { return result; } catch (IndexOutOfRangeException) { return result; }
if (cc == '}') {
GetChar();
return result;
}
object pkey = InterpretKey(type); object pkey = InterpretKey(type);
char c = GetChar(); char c = GetChar();
switch (c) { switch (c) {
@@ -183,19 +249,20 @@ namespace Cryville.Common.Pdt {
((IDictionary)result).Add(key, value); ((IDictionary)result).Add(key, value);
} }
else { else {
MemberInfo prop; MemberInfo prop = null;
bool flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop); bool flag = false;
if (!flag && pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey); 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); Type ptype = ReflectionHelper.GetMemberType(prop);
if (ReflectionHelper.IsGenericDictionary(ptype)) { if (flag) {
var ktype = ptype.GetGenericArguments()[0]; using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var vtype = ptype.GetGenericArguments()[1]; var ktype = ptype.GetGenericArguments()[0];
if (flag) { var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null); object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(vtype); 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)); else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
} }
@@ -211,28 +278,36 @@ namespace Cryville.Common.Pdt {
((IDictionary)result).Add(key, value); ((IDictionary)result).Add(key, value);
} }
else { else {
MemberInfo prop; MemberInfo prop = null;
bool flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop); bool flag = false;
if (!flag && pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey); 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); 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); object value = _binder.ChangeType(exp, ptype, null);
ReflectionHelper.SetValue(prop, result, value, _binder); 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; break;
case '}': default:
return result; 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) { protected virtual object InterpretKey(Type type) {
return tokenb(0x1000).Trim(); return tokenb(0x1000).Trim();
} }

View File

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

View File

@@ -1,4 +1,5 @@
using System; using System;
using UnsafeIL;
namespace Cryville.Common.Pdt { namespace Cryville.Common.Pdt {
/// <summary> /// <summary>
@@ -42,7 +43,9 @@ namespace Cryville.Common.Pdt {
/// <param name="dest">The destination buffer.</param> /// <param name="dest">The destination buffer.</param>
/// <param name="destOffset">The offset on the destination buffer to start copying to.</param> /// <param name="destOffset">The offset on the destination buffer to start copying to.</param>
/// <param name="length">The length to copy.</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) { public void CopyTo(byte* dest, int destOffset, int length) {
if (length > Length) throw new ArgumentOutOfRangeException("length");
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
dest[destOffset + i] = _ptr[i]; dest[destOffset + i] = _ptr[i];
} }
@@ -126,10 +129,43 @@ namespace Cryville.Common.Pdt {
throw new InvalidCastException("Not an identifier"); throw new InvalidCastException("Not an identifier");
return *(int*)(_ptr + offset); return *(int*)(_ptr + offset);
} }
internal void* TrustedAsOfLength(int len) { /// <summary>
if (Length < len) /// Gets the memory of the span as an instance of the specified type.
throw new InvalidCastException("Type not matched"); /// </summary>
return _ptr; /// <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> /// <summary>
/// Gets the array suffix. /// Gets the array suffix.

View File

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

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