1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-07-02 22:36:00 +02:00

Initial checkin

This commit is contained in:
Brian Fiete 2019-08-23 11:56:54 -07:00
parent c74712dad9
commit 078564ac9e
3242 changed files with 1616395 additions and 0 deletions

View file

@ -0,0 +1,105 @@
using System;
using System.Runtime.InteropServices;
namespace Beefy.utils
{
static class BeefPerf
{
[StdCall, CLink]
extern static void BpInit(char8* severName, char8* sessionName);
[StdCall, CLink]
extern static void BpShutdown();
[StdCall, CLink]
extern static void BpRetryConnect();
[StdCall, CLink]
extern static void BpPause();
[StdCall, CLink]
extern static void BpUnpause();
[StdCall, CLink]
extern static void BpSetThreadName(char8* threadName);
[StdCall, CLink]
extern static void BpEnter(char8* name);
[StdCall, CLink]
extern static void BpLeave();
[StdCall, CLink]
extern static void BpEvent(char8* name, char8* details);
[StdCall, CLink]
extern static char8* BpDynStr(char8* string);
public static void Init(StringView serverName, StringView sessionName)
{
BpInit(serverName.ToScopeCStr!(), sessionName.ToScopeCStr!());
}
public static void RetryConnect()
{
BpRetryConnect();
}
public static void Shutdown()
{
BpShutdown();
}
public static void Pause()
{
BpPause();
}
public static void Unpause()
{
BpUnpause();
}
public static void SetThreadName(StringView threadName)
{
BpSetThreadName(threadName.ToScopeCStr!());
}
[Inline]
public static void Enter(char8* name)
{
BpEnter(name);
}
[Inline]
public static void Leave()
{
BpLeave();
}
[Inline]
public static void Event(char8* name, char8* details)
{
BpEvent(name, details);
}
[Inline]
public static char8* DynStr(char8* string)
{
return BpDynStr(string);
}
}
class AutoBeefPerf
{
public this(char8* name)
{
BeefPerf.Enter(name);
}
public ~this()
{
BeefPerf.Leave();
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.utils
{
public delegate void DisposeProxyDelegate();
public class DisposeProxy : IDisposable
{
public DisposeProxyDelegate mDisposeProxyDelegate;
public this(DisposeProxyDelegate theDelegate = null)
{
mDisposeProxyDelegate = theDelegate;
}
public ~this()
{
delete mDisposeProxyDelegate;
}
public void Dispose()
{
mDisposeProxyDelegate();
}
}
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.utils
{
public interface ISerializable
{
//TODO: void Serialize(StructuredData data);
//TODO: void Deserialize(StructuredData data);
}
}

View file

@ -0,0 +1,899 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.utils
{
public struct IdSpan
{
enum Change
{
case Insert(int32 index, int32 id, int16 length);
case Remove(int32 index, int16 length);
public int32 GetIndex()
{
int32 index;
switch (this)
{
case .Insert(out index, ?, ?):
case .Remove(out index, ?):
}
return index;
}
}
enum ChangeKind
{
case None;
case Insert;
case Remove;
}
static uint8[] sEmptyData = new uint8[] { 0 } ~ delete _;
public uint8[] mData;
public int32 mLength;
List<Change> mChangeList;
public static int32 sId;
public int32 mId = ++sId;
public bool mAlwaysPrepare = false;
/*public uint8[] mData
{
get
{
Debug.Assert(mChangeList == null);
return mData;
}
}*/
public this()
{
mData = sEmptyData;
mLength = 0;
mChangeList = null;
}
public this(uint8[] data, int32 length)
{
mData = data;
mLength = length;
mChangeList = null;
}
bool HasChangeList
{
get
{
return mChangeList != null;
}
}
public bool IsEmpty
{
get
{
return mLength == 0;
}
}
struct Span
{
public int32 mIndex;
public int32 mId;
public int32 mLength;
public int32 mNext;
}
public void PrepareReverse() mut
{
PrepareReverse(0, mChangeList.Count);
DeleteAndNullify!(mChangeList);
}
// Decode change lists, move backwards through it applying changes, the reencode it.
// Repeats as necessary if items aren't in reverse order
void PrepareReverse(int startChangeIdx, int endChangeIdx) mut
{
int changeIdx = startChangeIdx;
List<Span> spans = scope List<Span>();
while (changeIdx < endChangeIdx)
{
spans.Clear();
int encodeIdx = 0;
int32 charId = 1;
int32 charIdx = 0;
while (true)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
{
charId = cmd;
}
else
{
int32 spanSize = -cmd;
if (cmd == 0)
break;
Span span;
span.mId = charId;
span.mIndex = charIdx;
span.mLength = spanSize;
span.mNext = -1;
spans.Add(span);
charId += spanSize;
charIdx += spanSize;
if (spans.Count > 1)
spans[spans.Count - 2].mNext = (int32)spans.Count - 1;
}
}
// Initialize to something so we can pick up the insert
if (spans.Count == 0)
{
Span span;
span.mId = 1;
span.mIndex = 0;
span.mLength = 0;
span.mNext = -1;
spans.Add(span);
}
int32 index = -1;
int32 length = -1;
int32 curId = -1;
ChangeKind changeKind = .None;
int32 checkIdx = (int32)spans.Count - 1;
int32 headSpanIdx = 0;
// Reverse find the first span
while ((checkIdx >= 0) && (changeIdx < endChangeIdx))
{
if (changeKind == .None)
{
switch (mChangeList[changeIdx])
{
case .Insert(out index, out curId, out length):
changeKind = .Insert;
case .Remove(out index, out length):
changeKind = .Remove;
}
}
var checkSpan = ref spans[checkIdx];
if ((index >= checkSpan.mIndex) && (index <= checkSpan.mIndex + checkSpan.mLength))
{
if (changeKind == .Insert)
{
if (index == checkSpan.mIndex)
{
if (checkSpan.mLength == 0)
{
checkSpan.mLength = length;
checkSpan.mId = curId;
}
else
{
int32 newSpanIdx = (.)spans.Count;
// Insert before span
Span span;
span.mIndex = index;
span.mId = curId;
span.mLength = length;
span.mNext = (.)checkIdx;
spans.Add(span);
if (checkIdx > 0)
{
Debug.Assert(spans[checkIdx - 1].mNext == checkIdx);
spans[checkIdx - 1].mNext = newSpanIdx;
}
else
headSpanIdx = newSpanIdx;
// Since we remapped the previous entries mNext, we are no longer in order and can't be reused this pass
checkIdx = checkIdx - 1;
}
}
else
{
var checkSpan;
// Split span
int32 leftLength = index - checkSpan.mIndex;
int32 newSpanId = (.)spans.Count;
int32 newRightId = (.)spans.Count + 1;
@checkSpan.mNext = newSpanId;
@checkSpan.mLength = leftLength;
Span span;
span.mIndex = index;
span.mId = curId;
span.mLength = length;
span.mNext = newRightId;
spans.Add(span);
Span rightSpan;
rightSpan.mIndex = index + span.mLength;
rightSpan.mId = checkSpan.mId + leftLength;
rightSpan.mLength = checkSpan.mLength - leftLength;
rightSpan.mNext = checkSpan.mNext;
spans.Add(rightSpan);
}
}
else // Remove
{
int removeSpanIdx = checkIdx;
if (index == checkSpan.mIndex)
{
// Removing from front of span. Handled in loop below.
}
else if (index + length >= checkSpan.mIndex + checkSpan.mLength)
{
// Removing up to or past end of span
int32 removeCount = Math.Min(length, checkSpan.mLength - (index - checkSpan.mIndex));
checkSpan.mLength -= removeCount;
length -= removeCount;
removeSpanIdx = checkSpan.mNext;
}
else
{
var checkSpan;
int32 splitIdx = index - checkSpan.mIndex;
int32 splitOfs = splitIdx + length;
int32 newRightId = (.)spans.Count;
@checkSpan.mNext = newRightId;
@checkSpan.mLength = index - checkSpan.mIndex;
Span rightSpan;
rightSpan.mIndex = checkSpan.mIndex + splitIdx;
rightSpan.mId = checkSpan.mId + splitOfs;
rightSpan.mLength = checkSpan.mLength - splitOfs;
rightSpan.mNext = checkSpan.mNext;
spans.Add(rightSpan);
length = 0;
if (newRightId == checkIdx + 1)
checkIdx = newRightId; // rightSpan index is valid now and it is next in sequence
}
while (length > 0)
{
var removeSpan = ref spans[removeSpanIdx];
// Remove from start of span
int32 removeCount = Math.Min(removeSpan.mLength, length);
removeSpan.mId += removeCount;
removeSpan.mLength -= removeCount;
length -= removeCount;
removeSpanIdx = removeSpan.mNext;
}
}
changeIdx++;
changeKind = .None;
continue;
}
checkIdx--;
}
curId = 1;
int32 spanIdx = headSpanIdx;
int curEncodeIdx = 0;
if (mData != sEmptyData)
delete mData;
mData = new uint8[spans.Count * 8];
while (spanIdx != -1)
{
var span = ref spans[spanIdx];
if (span.mLength == 0)
{
spanIdx = span.mNext;
continue;
}
if (span.mId != curId)
{
Utils.EncodeInt(mData, ref curEncodeIdx, span.mId);
curId = span.mId;
}
Utils.EncodeInt(mData, ref curEncodeIdx, -span.mLength);
curId += span.mLength;
spanIdx = span.mNext;
}
Utils.EncodeInt(mData, ref curEncodeIdx, 0);
mLength = (int32)curEncodeIdx;
}
}
void MaybePrepare() mut
{
// For sanity - only queue up so many changes
if (mChangeList.Count >= 8192)
{
Prepare();
}
}
public void Prepare() mut
{
if (mChangeList == null)
return;
scope AutoBeefPerf("IdSpan.Prepare");
int changeIdx = 0;
while (changeIdx < mChangeList.Count)
{
// Check to see if we have a reverse-order encoding. This can occur when undoing forward-ordered changes (for example)
bool hasReverse = false;
int reverseLastIdx = changeIdx;
int32 prevIndex = mChangeList[changeIdx].GetIndex();
for (int checkIdx = changeIdx + 1; checkIdx < mChangeList.Count; checkIdx++)
{
int32 nextIndex = mChangeList[checkIdx].GetIndex();
if (nextIndex > prevIndex)
break;
if (nextIndex < prevIndex)
hasReverse = true;
reverseLastIdx = checkIdx;
prevIndex = nextIndex;
}
if (hasReverse)
{
PrepareReverse(changeIdx, reverseLastIdx + 1);
changeIdx = reverseLastIdx + 1;
continue;
}
// We need space to encode '-length', the new span ID,
// reverting back to the original ID, and a split span length
uint8[] textIdData = new uint8[mLength + mChangeList.Count*16];
int prevCharIdx = 0;
int prevEncodeIdx = 0;
int prevLastSpanLength = 0;
int prevLastSpanIdStart = 1;
int curEncodeIdx = 0;
int curSpanIdStart = 1;
bool foundSpan = false;
int ignoreLength = 0;
int32 index;
int32 length;
int32 curId = -1;
ChangeKind changeKind;
switch (mChangeList[changeIdx++])
{
case .Insert(out index, out curId, out length):
changeKind = .Insert;
case .Remove(out index, out length):
changeKind = .Remove;
}
while (prevLastSpanIdStart != -1)
{
if (ignoreLength > 0)
{
int handleLength = Math.Min(prevLastSpanLength, ignoreLength);
ignoreLength -= handleLength;
prevLastSpanIdStart += handleLength;
prevLastSpanLength -= handleLength;
}
if ((curSpanIdStart != prevLastSpanIdStart) && (prevLastSpanLength > 0) && (ignoreLength == 0))
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, prevLastSpanIdStart);
curSpanIdStart = prevLastSpanIdStart;
}
if ((prevCharIdx + prevLastSpanLength >= index) && (!foundSpan) && (ignoreLength == 0))
{
foundSpan = true;
if (curSpanIdStart != prevLastSpanIdStart)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, prevLastSpanIdStart);
curSpanIdStart = prevLastSpanIdStart;
}
if (changeKind case .Insert)
{
// Time to insert
int leftSplitLen = index - prevCharIdx;
if (leftSplitLen > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -leftSplitLen);
curSpanIdStart += leftSplitLen;
prevLastSpanIdStart += leftSplitLen;
prevCharIdx += leftSplitLen;
prevLastSpanLength -= leftSplitLen;
}
if (curSpanIdStart != curId)
{
curSpanIdStart = curId;
Utils.EncodeInt(textIdData, ref curEncodeIdx, curSpanIdStart);
}
curId += length;
if (length > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -length);
curSpanIdStart += length;
prevCharIdx += length;
}
}
else
{
ignoreLength = length;
// Time to insert
int leftSplitLen = index - prevCharIdx;
if (leftSplitLen > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -leftSplitLen);
curSpanIdStart += leftSplitLen;
prevLastSpanIdStart += leftSplitLen;
prevCharIdx += leftSplitLen;
prevLastSpanLength -= leftSplitLen;
}
}
if (changeIdx < mChangeList.Count)
{
switch (mChangeList[changeIdx])
{
case .Insert(out index, out curId, out length):
changeKind = .Insert;
case .Remove(out index, out length):
changeKind = .Remove;
}
if (index >= prevCharIdx)
{
// We are inserting into a just-removed location
foundSpan = false;
changeIdx++;
}
}
continue;
}
int cmd = Utils.DecodeInt(mData, ref prevEncodeIdx);
if (cmd >= 0)
{
if (prevLastSpanLength > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -prevLastSpanLength);
curSpanIdStart += prevLastSpanLength;
prevLastSpanIdStart += prevLastSpanLength;
prevCharIdx += prevLastSpanLength;
prevLastSpanLength = 0;
}
Debug.Assert(prevLastSpanLength == 0);
prevLastSpanIdStart = cmd;
if (cmd == 0)
break;
}
else
prevLastSpanLength += -cmd;
}
Utils.EncodeInt(textIdData, ref curEncodeIdx, 0);
mLength = (int32)curEncodeIdx;
if (mData != sEmptyData)
delete mData;
mData = textIdData;
}
DeleteAndNullify!(mChangeList);
}
public IdSpan GetPrepared() mut
{
Prepare();
return this;
}
public void Dispose() mut
{
if (mData != sEmptyData)
delete mData;
delete mChangeList;
mData = sEmptyData;
mLength = 0;
}
public void DuplicateFrom(ref IdSpan span) mut
{
Dispose();
this = span.Duplicate();
}
public static readonly IdSpan Empty = IdSpan(sEmptyData, 1);
public void Insert(int index, int length, ref int32 curId) mut
{
var index;
var length;
if (mChangeList == null)
mChangeList = new .();
else if (mChangeList.Count > 0)
{
var change = ref mChangeList.Back;
if (change case .Insert(let prevIndex, let prevId, var ref prevLength))
{
if ((prevIndex + prevLength == index) && (prevId + prevLength == curId))
{
int16 curLen = (int16)Math.Min(length, 0x7FFF - prevLength);
prevLength += curLen;
curId += curLen;
index += curLen;
length -= curLen;
}
}
}
while (length > 0)
{
int16 curLen = (int16)Math.Min(length, 0x7FFF);
mChangeList.Add(.Insert((int32)index, curId, curLen));
curId += curLen;
index += curLen;
length -= curLen;
}
if (mAlwaysPrepare)
Prepare();
else
MaybePrepare();
}
public void Remove(int index, int length) mut
{
var index;
var length;
if (mChangeList == null)
mChangeList = new .();
else if (mChangeList.Count > 0)
{
var change = ref mChangeList.Back;
if (change case .Remove(let prevIndex, var ref prevLength))
{
if (prevIndex == index)
{
int16 curLen = (int16)Math.Min(length, 0x7FFF - prevLength);
prevLength += curLen;
length -= curLen;
}
}
}
while (length > 0)
{
int16 curLen = (int16)Math.Min(length, 0x7FFF);
mChangeList.Add(.Remove((int32)index, curLen));
length -= curLen;
}
if (mAlwaysPrepare)
Prepare();
else
MaybePrepare();
}
public int GetIndexFromId(int32 findCharId)
{
Debug.Assert(!HasChangeList);
int encodeIdx = 0;
int charId = 1;
int charIdx = 0;
while (true)
{
int cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
charId = cmd;
else
{
int spanSize = -cmd;
if ((findCharId >= charId) && (findCharId < charId + spanSize))
return charIdx + (findCharId - charId);
charId += spanSize;
charIdx += spanSize;
if (cmd == 0)
return -1;
}
}
}
public int32 GetIdAtIndex(int findIndex)
{
int encodeIdx = 0;
int32 charId = 1;
int charIdx = 0;
while (true)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
charId = cmd;
else
{
int32 spanSize = -cmd;
if ((findIndex >= charIdx) && (findIndex < charIdx + spanSize))
return charId + (int32)(findIndex - charIdx);
charId += spanSize;
charIdx += spanSize;
if (cmd == 0)
return -1;
}
}
}
public IdSpan Duplicate()
{
Debug.Assert(!HasChangeList);
IdSpan idSpan = IdSpan();
if (mData != null)
{
idSpan.mData = new uint8[mLength];
mData.CopyTo(idSpan.mData, 0, 0, mLength);
idSpan.mLength = mLength;
}
return idSpan;
}
public bool Equals(IdSpan idData2)
{
Debug.Assert(!HasChangeList);
Debug.Assert(!idData2.HasChangeList);
if ((mLength == 0) || (idData2.mLength == 0))
return (mLength == 0) && (idData2.mLength == 0);
int encodeIdx1 = 0;
int encodeIdx2 = 0;
int curSpanId1 = 1;
int curSpanId2 = 1;
int spanLen1 = 0;
int spanLen2 = 0;
while (true)
{
while (spanLen1 == 0)
{
int cmd = Utils.DecodeInt(mData, ref encodeIdx1);
if (cmd < 0)
{
spanLen1 = -cmd;
}
else
{
curSpanId1 = cmd;
if (cmd == 0)
break;
}
}
while (spanLen2 == 0)
{
int32 cmd = Utils.DecodeInt(idData2.mData, ref encodeIdx2);
if (cmd < 0)
{
spanLen2 = -cmd;
}
else
{
curSpanId2 = cmd;
if (cmd == 0)
{
// They are equal if both spans are at the end
return spanLen1 == 0;
}
}
}
if (curSpanId1 != curSpanId2)
return false;
int minLen = Math.Min(spanLen1, spanLen2);
curSpanId1 += minLen;
spanLen1 -= minLen;
curSpanId2 += minLen;
spanLen2 -= minLen;
}
}
public int GetTotalLength()
{
int len = 0;
int encodeIdx = 0;
while (true)
{
int cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd == 0)
return len;
if (cmd < 0)
len += -cmd;
}
}
static bool FindId(uint8[] idData, ref int encodeIdx, ref int32 curSpanId, ref int32 spanLen, int32 findSpanId)
{
while (true)
{
int32 cmd = Utils.DecodeInt(idData, ref encodeIdx);
if (cmd < 0)
{
spanLen = -cmd;
if ((findSpanId >= curSpanId) && (findSpanId < curSpanId + spanLen))
{
int32 delta = findSpanId - curSpanId;
curSpanId += delta;
spanLen -= delta;
return true;
}
curSpanId += spanLen;
}
else
{
curSpanId = cmd;
if (cmd == 0)
return false;
}
}
}
public bool IsRangeEqual(IdSpan idData2, int32 startCharId, int32 endCharId)
{
int encodeIdx1 = 0;
int encodeIdx2 = 0;
int32 curSpanId1 = 1;
int32 curSpanId2 = 1;
int32 spanLen1 = 0;
int32 spanLen2 = 0;
if (!FindId(mData, ref encodeIdx1, ref curSpanId1, ref spanLen1, startCharId))
return false;
if (!FindId(idData2.mData, ref encodeIdx2, ref curSpanId2, ref spanLen2, startCharId))
return false;
while (true)
{
while (spanLen1 == 0)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx1);
if (cmd < 0)
{
spanLen1 = -cmd;
}
else
{
curSpanId1 = cmd;
if (cmd == 0)
break;
}
}
while (spanLen2 == 0)
{
int32 cmd = Utils.DecodeInt(idData2.mData, ref encodeIdx2);
if (cmd < 0)
{
spanLen2 = -cmd;
}
else
{
curSpanId2 = cmd;
if (cmd == 0)
{
// They are equal if both spans are at the end
return spanLen1 == 0;
}
}
}
if (curSpanId1 != curSpanId2)
return false;
if (curSpanId1 == endCharId)
return true;
int minLen = Math.Min(spanLen1, spanLen2);
if ((endCharId >= curSpanId1) && (endCharId < curSpanId1 + minLen))
minLen = Math.Min(minLen, endCharId - curSpanId1);
if ((endCharId >= curSpanId2) && (endCharId < curSpanId2 + minLen))
minLen = Math.Min(minLen, endCharId - curSpanId2);
curSpanId1 += (int32)minLen;
spanLen1 -= (.)minLen;
curSpanId2 += (int32)minLen;
spanLen2 -= (.)minLen;
}
}
public static IdSpan GetDefault(int32 length)
{
uint8[] idData = new uint8[8];
int encodeIdx = 0;
Utils.EncodeInt(idData, ref encodeIdx, (int32)-length);
Utils.EncodeInt(idData, ref encodeIdx, 0);
IdSpan idSpan = IdSpan();
idSpan.mData = idData;
idSpan.mLength = (int32)encodeIdx;
return idSpan;
}
public void Dump() mut
{
Prepare();
Debug.WriteLine("IdSpan Dump:");
int encodeIdx = 0;
int charId = 1;
int charIdx = 0;
while (true)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
{
charId = cmd;
Debug.WriteLine(" Id: {0}", charId);
}
else
{
int32 spanSize = -cmd;
charId += spanSize;
charIdx += spanSize;
if (cmd == 0)
return;
Debug.WriteLine(" Len: {0}", spanSize);
}
}
}
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime;
using System.Diagnostics;
namespace Beefy.utils
{
public static class ManualBreak
{
public static void Break()
{
ThrowUnimplemented();
//Debugger.Break();
}
}
}

View file

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Beefy.utils
{
public abstract class PerfTimer
{
[StdCall, CLink]
extern static void PerfTimer_ZoneStart(char8* name);
[StdCall, CLink]
extern static void PerfTimer_ZoneEnd();
[StdCall, CLink]
extern static void PerfTimer_Message(char8* theString);
[StdCall, CLink]
extern static int32 PerfTimer_IsRecording();
[StdCall, CLink]
extern static void PerfTimer_StartRecording();
[StdCall, CLink]
extern static void PerfTimer_StopRecording();
[StdCall, CLink]
extern static void PerfTimer_DbgPrint();
static DisposeProxy mZoneEndDisposeProxy ~ delete _;
public static DisposeProxy ZoneStart(String name)
{
if (mZoneEndDisposeProxy == null)
mZoneEndDisposeProxy = new DisposeProxy(new => ZoneEnd);
PerfTimer_ZoneStart(name);
return mZoneEndDisposeProxy;
}
public static void ZoneEnd()
{
PerfTimer_ZoneEnd();
}
public static void Message(String theString)
{
PerfTimer_Message(theString);
}
public static void Message(String format, params Object[] theParams)
{
String outStr = scope String();
outStr.AppendF(format, params theParams);
Message(outStr);
}
public static bool IsRecording()
{
return PerfTimer_IsRecording() != 0;
}
public static void StartRecording()
{
PerfTimer_StartRecording();
}
public static void StopRecording()
{
PerfTimer_StopRecording();
}
public static void DbgPrint()
{
PerfTimer_DbgPrint();
}
}
}

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.utils
{
public class SmoothValue
{
public double mSrc;
public double mDest;
public float mPct;
public float mSpeed = 1.0f;
public float mSpeedScale = 1.0f;
public double v
{
get
{
if (mPct == 1.0f)
return mDest;
return mSrc + (mDest - mSrc) * EasedPct;
}
}
public double EasedPct
{
get
{
if (mPct == 1.0f)
return 1.0f;
return Utils.EaseInAndOut(mPct);
}
}
public bool IsMoving
{
get { return mPct != 1.0f; }
}
public void Update()
{
mPct = Math.Min(1.0f, mPct + mSpeed * mSpeedScale);
}
public void Set(double val, bool immediate = false)
{
if ((!immediate) && (val == mDest))
return;
if ((mPct != 1.0f) && (mPct != 0.0f))
{
double cur = v;
if (mPct > 0.80f)
mPct = 0.80f;
mDest = val;
mSrc = -(cur - mDest * EasedPct) / (EasedPct - 1);
mSpeedScale = (1.0f - mPct);
}
else
{
mSrc = v;
mPct = 0.0f;
mSpeedScale = 1.0f;
mDest = val;
}
if (immediate)
mPct = 1.0f;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
namespace Beefy.utils
{
class TextSearcher
{
enum CmdKind
{
Contains,
NotContains,
Equals,
}
struct CmdElement
{
public CmdKind mKind;
public String mString;
}
List<CmdElement> mCmds = new List<CmdElement>() ~
{
for (var cmdElement in mCmds)
{
delete cmdElement.mString;
}
delete _;
};
Result<void> EndCmd(String findStr, ref char8 startChar, String outError, OperatorDelegate operatorHandler)
{
if (findStr.IsEmpty)
return .Ok;
CmdElement cmdElement;
if ((findStr.StartsWith(":")) && (operatorHandler != null))
{
int opIdx = -1;
for (int i < findStr.Length)
{
char8 c = findStr[i];
if ((c == '=') || (c == '>') || (c == '<'))
{
if (opIdx != -1)
{
outError.Append("Multiple operators cannot be defined in the same text segment");
return .Err;
}
opIdx = i;
}
}
if (opIdx != -1)
{
if (startChar != 0)
{
outError.Append("Multiple operators cannot be defined in the same text segment");
return .Err;
}
if ((operatorHandler == null) || (!operatorHandler(scope String(findStr, 0, opIdx), findStr[opIdx], scope String(findStr, opIdx + 1))))
{
outError.AppendF("Invalid expression: {0}", findStr);
return .Err;
}
return .Ok;
}
}
if (startChar == '=')
cmdElement.mKind = .Equals;
else if (startChar == '-')
cmdElement.mKind = .NotContains;
else
cmdElement.mKind = .Contains;
cmdElement.mString = new String(findStr);
mCmds.Add(cmdElement);
findStr.Clear();
startChar = 0;
return .Ok;
}
delegate bool OperatorDelegate(String lhs, char8 op, String rhs);
public Result<void> Init(String searchStr, String outError, OperatorDelegate operatorHandler = null)
{
bool inQuote = false;
char8 startChar = 0;
String findStr = scope String();
for (int i < searchStr.Length)
{
var c = searchStr[i];
if (c == '\"')
{
inQuote = !inQuote;
continue;
}
if (c == '\"')
{
c = searchStr[++i];
findStr.Append(c);
continue;
}
if ((c == ' ') && (!inQuote))
{
Try!(EndCmd(findStr, ref startChar, outError, operatorHandler));
continue;
}
if ((startChar == 0) && (findStr.IsEmpty) && (!inQuote))
{
if ((c == '=') || (c == '-'))
{
startChar = c;
continue;
}
}
findStr.Append(c);
}
Try!(EndCmd(findStr, ref startChar, outError, operatorHandler));
return .Ok;
}
public bool Matches(String checkStr)
{
for (var cmd in ref mCmds)
{
switch (cmd.mKind)
{
case .Contains:
if (checkStr.IndexOf(cmd.mString, true) == -1)
return false;
case .NotContains:
if (checkStr.IndexOf(cmd.mString, true) != -1)
return false;
case .Equals:
if (!String.Equals(checkStr, cmd.mString, .OrdinalIgnoreCase))
return false;
}
}
return true;
}
public bool IsEmpty
{
get
{
return mCmds.Count == 0;
}
}
}
}

View file

@ -0,0 +1,311 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace Beefy.utils
{
public class UndoAction
{
public virtual bool Merge(UndoAction nextAction)
{
return false;
}
public virtual bool Undo()
{
return true;
}
public virtual bool Redo()
{
return true;
}
public virtual int32 GetCost()
{
return 1;
}
}
public interface IUndoBatchStart
{
IUndoBatchEnd BatchEnd { get; }
String Name { get; }
}
public interface IUndoBatchEnd
{
IUndoBatchStart BatchStart { get; }
String Name { get; }
}
public class UndoBatchStart : UndoAction, IUndoBatchStart
{
public String mName;
public UndoBatchEnd mBatchEnd;
public int32 mBatchInsertIdx;
public int32 mBatchSize = 0; // Don't close out until we add the end
public String Name
{
get
{
return mName;
}
}
public this(String name)
{
mName = name;
mBatchEnd = new UndoBatchEnd();
mBatchEnd.mBatchStart = this;
}
public IUndoBatchEnd BatchEnd
{
get
{
return mBatchEnd;
}
}
public override int32 GetCost()
{
return Math.Min(mBatchSize, 256); // Don't allow a large batch (ie: rename) to cause us to pull too much out of the undo buffer
}
}
public class UndoBatchEnd : UndoAction, IUndoBatchEnd
{
public IUndoBatchStart mBatchStart;
public String Name
{
get
{
return mBatchStart.Name;
}
}
public IUndoBatchStart BatchStart
{
get
{
return mBatchStart;
}
}
}
public class UndoManager
{
List<UndoAction> mUndoList = new List<UndoAction>() ~ DeleteContainerAndItems!(_);
int32 mUndoIdx = 0;
int32 mMaxCost = 8192;
int32 mCurCost = 0;
bool mSkipNextMerge; // Don't merge after we do an undo or redo step
int32 mFreezeDeletes;
public ~this()
{
Clear();
}
public void WithActions(Action<UndoAction> func)
{
for (var action in mUndoList)
func(action);
}
public void Clear()
{
while (mUndoList.Count > 0)
{
var undoAction = mUndoList.PopBack();
delete undoAction;
}
mUndoIdx = 0;
mCurCost = 0;
}
public void Add(UndoAction action, bool allowMerge = true)
{
if (mFreezeDeletes == 0)
mCurCost += action.GetCost();
if (action is IUndoBatchStart)
{
mFreezeDeletes++;
if (var undoBatchStart = action as UndoBatchStart)
{
undoBatchStart.mBatchInsertIdx = GetActionCount();
}
}
else if (action is IUndoBatchEnd)
{
mFreezeDeletes--;
if (var undoBatchEnd = action as UndoBatchEnd)
{
if (var undoBatchStart = undoBatchEnd.mBatchStart as UndoBatchStart)
{
undoBatchStart.mBatchSize = GetActionCount() - undoBatchStart.mBatchInsertIdx;
int32 cost = undoBatchStart.GetCost();
Debug.Assert(cost >= 0);
mCurCost += cost;
}
}
}
if (mUndoIdx < mUndoList.Count)
{
int32 batchDepth = 0;
for (int checkIdx = mUndoIdx; checkIdx < mUndoList.Count; checkIdx++)
{
var checkAction = mUndoList[checkIdx];
if (batchDepth == 0)
mCurCost -= checkAction.GetCost();
if (checkAction is IUndoBatchStart)
batchDepth++;
else if (checkAction is IUndoBatchEnd)
batchDepth--;
delete checkAction;
}
Debug.Assert(batchDepth == 0);
mUndoList.RemoveRange(mUndoIdx, mUndoList.Count - mUndoIdx);
}
if ((allowMerge) && (!mSkipNextMerge))
{
UndoAction prevAction = GetLastUndoAction();
if (prevAction is UndoBatchStart)
{
var undoBatchStart = (UndoBatchStart)prevAction;
if (undoBatchStart.mBatchEnd == action)
{
// It's an empty batch!
mUndoList.PopBack();
delete prevAction;
delete action;
mUndoIdx--;
return;
}
}
if ((prevAction != null) && (prevAction.Merge(action)))
{
delete action;
return;
}
}
mSkipNextMerge = false;
mUndoList.Add(action);
mUndoIdx++;
if ((mCurCost > mMaxCost) && (mFreezeDeletes == 0))
{
int32 wantCost = (int32)(mMaxCost * 0.8f); // Don't just remove one item at a time
int32 checkIdx = 0;
int32 batchDepth = 0;
while (((mCurCost > wantCost) || (batchDepth > 0)) &&
(checkIdx < mUndoList.Count))
{
var checkAction = mUndoList[checkIdx];
if (batchDepth == 0)
mCurCost -= checkAction.GetCost();
if (checkAction is IUndoBatchStart)
batchDepth++;
else if (checkAction is IUndoBatchEnd)
batchDepth--;
delete checkAction;
checkIdx++;
}
mUndoList.RemoveRange(0, checkIdx);
mUndoIdx -= checkIdx;
}
}
public UndoAction GetLastUndoAction()
{
if (mUndoIdx == 0)
return null;
return mUndoList[mUndoIdx - 1];
}
public bool Undo()
{
mSkipNextMerge = true;
if (mUndoIdx == 0)
return false;
var undoAction = mUndoList[mUndoIdx - 1];
if (IUndoBatchEnd undoBatchEnd = undoAction as IUndoBatchEnd)
{
while (true)
{
if (!undoAction.Undo())
return false;
if (mUndoIdx == 0)
return false;
mUndoIdx--;
if ((undoAction == undoBatchEnd.BatchStart) || (mUndoIdx == 0))
return true;
undoAction = mUndoList[mUndoIdx - 1];
}
}
if (!undoAction.Undo())
return false;
mUndoIdx--;
return true;
}
public bool Redo()
{
mSkipNextMerge = true;
if (mUndoIdx >= mUndoList.Count)
return false;
int32 startUndoIdx = mUndoIdx;
var undoAction = mUndoList[mUndoIdx];
if (undoAction is UndoBatchStart)
{
UndoBatchStart undoBatchStart = (UndoBatchStart)undoAction;
while (true)
{
if (!undoAction.Redo())
{
mUndoIdx = startUndoIdx;
return false;
}
if (mUndoIdx >= mUndoList.Count)
return false;
mUndoIdx++;
if (undoAction == undoBatchStart.mBatchEnd)
return true;
undoAction = mUndoList[mUndoIdx];
}
}
if (!undoAction.Redo())
return false;
mUndoIdx++;
return true;
}
public int32 GetActionCount()
{
return mUndoIdx;
}
}
}