144 lines
5.6 KiB
C#
144 lines
5.6 KiB
C#
using System;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
|
|
namespace Cryville.Common.Pdt {
|
|
/// <summary>
|
|
/// Span on the memory of a <see cref="PdtEvaluatorBase" />.
|
|
/// </summary>
|
|
public unsafe struct PdtVariableMemory {
|
|
byte* _ptr;
|
|
/// <summary>
|
|
/// The length of the span.
|
|
/// </summary>
|
|
public int Length { get; private set; }
|
|
/// <summary>
|
|
/// The type of the span.
|
|
/// </summary>
|
|
public int Type { get; private set; }
|
|
internal PdtVariableMemory(int type, byte* ptr, int len) {
|
|
Type = type;
|
|
_ptr = ptr;
|
|
Length = len;
|
|
}
|
|
/// <summary>
|
|
/// Copies the memory in the span to a buffer.
|
|
/// </summary>
|
|
/// <param name="dest">The destination buffer.</param>
|
|
/// <param name="destOffset">The offset on the destination buffer to start copying to.</param>
|
|
public void CopyTo(byte[] dest, int destOffset) {
|
|
fixed (byte* ptr = dest) {
|
|
CopyTo(ptr, destOffset, Length);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Copies the memory in the span to a buffer.
|
|
/// </summary>
|
|
/// <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>
|
|
public void CopyTo(byte* dest, int destOffset, int length) {
|
|
for (int i = 0; i < length; i++)
|
|
dest[destOffset + i] = _ptr[i];
|
|
}
|
|
/// <summary>
|
|
/// Gets the memory of the span as a number.
|
|
/// </summary>
|
|
/// <returns>A number.</returns>
|
|
/// <exception cref="InvalidCastException">The span does not represent a number.</exception>
|
|
public float AsNumber() {
|
|
if (Type != PdtInternalType.Number)
|
|
throw new InvalidCastException("Not a number");
|
|
float value;
|
|
byte* ptr = (byte*)&value;
|
|
for (int i = 0; i < sizeof(float); i++)
|
|
ptr[i] = _ptr[i];
|
|
return value;
|
|
}
|
|
/// <summary>
|
|
/// Sets the memory of the span to a number.
|
|
/// </summary>
|
|
/// <param name="value">The number.</param>
|
|
/// <exception cref="InvalidCastException">The span does not represent a number.</exception>
|
|
public void SetNumber(float value) {
|
|
if (Type != PdtInternalType.Number)
|
|
throw new InvalidCastException("Not a number");
|
|
byte* ptr = (byte*)&value;
|
|
for (int i = 0; i < sizeof(float); i++)
|
|
_ptr[i] = ptr[i];
|
|
}
|
|
/// <summary>
|
|
/// Gets the memory of the span as a string.
|
|
/// </summary>
|
|
/// <param name="offset">The offset on the span to start reading from.</param>
|
|
/// <returns>A string.</returns>
|
|
/// <exception cref="InvalidCastException">The span at the offset does not represent a string.</exception>
|
|
public string AsString(int offset = 0) {
|
|
if (Type != PdtInternalType.String && Type != PdtInternalType.Array)
|
|
throw new InvalidCastException("Not a string");
|
|
var len = *(int*)(_ptr + offset);
|
|
return new string((char*)(_ptr + offset + sizeof(int)), 0, len);
|
|
}
|
|
/// <summary>
|
|
/// Sets the memory of the span to a string.
|
|
/// </summary>
|
|
/// <param name="value">The string.</param>
|
|
/// <param name="offset">The offset from the start of the span.</param>
|
|
/// <exception cref="InvalidCastException">The span at the offset does not represent a string.</exception>
|
|
/// <exception cref="InvalidOperationException">The length of the span is not sufficient.</exception>
|
|
public void SetString(string value, int offset = 0) {
|
|
if (Type != PdtInternalType.String && Type != PdtInternalType.Array)
|
|
throw new InvalidCastException("Not a string");
|
|
int strlen = value.Length;
|
|
if (Length < strlen * sizeof(char) + sizeof(int) + offset)
|
|
throw new InvalidOperationException("Frame length not sufficient");
|
|
char* ptr = (char*)(_ptr + offset + sizeof(int));
|
|
*(int*)(_ptr + offset) = strlen;
|
|
int i = 0;
|
|
foreach (var c in value) ptr[i++] = c;
|
|
}
|
|
/// <summary>
|
|
/// Gets the memory of the span as an undefined identifier.
|
|
/// </summary>
|
|
/// <param name="offset">The offset on the span to start reading from.</param>
|
|
/// <returns>The name of an undefined identifier.</returns>
|
|
/// <exception cref="InvalidCastException">The span does not represent an undefined identifier.</exception>
|
|
public string AsIdentifier(int offset = 0) {
|
|
if (Type != PdtInternalType.Undefined && Type != PdtInternalType.Array)
|
|
throw new InvalidCastException("Not an identifier");
|
|
var len = *(int*)(_ptr + offset);
|
|
return new string((char*)(_ptr + offset + sizeof(int)), 0, len);
|
|
}
|
|
internal void* TrustedAsOfLength(int len) {
|
|
if (Length < len)
|
|
throw new InvalidCastException("Type not matched");
|
|
return _ptr;
|
|
}
|
|
/// <summary>
|
|
/// Gets the array suffix.
|
|
/// </summary>
|
|
/// <param name="arrtype">The type of the array.</param>
|
|
/// <param name="pc">The item count of the array.</param>
|
|
/// <exception cref="InvalidCastException">The span does not represent an array.</exception>
|
|
public void GetArraySuffix(out int arrtype, out int pc) {
|
|
if (Type != PdtInternalType.Array && Type != PdtInternalType.Array)
|
|
throw new InvalidCastException("Not an array or vector");
|
|
arrtype = *(int*)(_ptr + Length - sizeof(int));
|
|
if (Type == PdtInternalType.Array) pc = *(int*)(_ptr + Length - 2 * sizeof(int));
|
|
else pc = -1;
|
|
}
|
|
/// <summary>
|
|
/// Sets the array suffix.
|
|
/// </summary>
|
|
/// <param name="arrtype">The type of the array.</param>
|
|
/// <param name="pc">The item count of the array.</param>
|
|
/// <exception cref="InvalidCastException">The span does not represent an array.</exception>
|
|
public void SetArraySuffix(int arrtype, int pc = 0) {
|
|
if (Type != PdtInternalType.Vector && Type != PdtInternalType.Array)
|
|
throw new InvalidCastException("Not an array or vector");
|
|
*(int*)(_ptr + Length - sizeof(int)) = arrtype;
|
|
if (Type == PdtInternalType.Array) *(int*)(_ptr + Length - 2 * sizeof(int)) = pc;
|
|
}
|
|
}
|
|
}
|