diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
commit | 37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch) | |
tree | eaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/LArray.cpp | |
download | t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip |
initial commit
Diffstat (limited to '')
-rw-r--r-- | src/T2DLL/LArray.cpp | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/src/T2DLL/LArray.cpp b/src/T2DLL/LArray.cpp new file mode 100644 index 0000000..647162f --- /dev/null +++ b/src/T2DLL/LArray.cpp @@ -0,0 +1,406 @@ +#include "LArray.h" +#include "T2Archive.h" + +// unknown/assumed name -- not in T2DLL exports! +class LDefaultComparator : public LComparator { +public: + LDefaultComparator(); + virtual ~LDefaultComparator(); + virtual int Compare(const void* inItemOne, const void* inItemTwo, unsigned int inSizeOne, unsigned int inSizeTwo) const; + virtual BOOL IsEqualTo(const void* inItemOne, const void* inItemTwo, unsigned int inSizeOne, unsigned int inSizeTwo) const; + static LDefaultComparator* GetComparator(); +protected: + static LDefaultComparator* sDefaultComparator; +}; + +LArray::LArray() { + init(sizeof(void *), NULL, false); +} + +LArray::LArray(int size, LComparator* comparator, BOOL keepSorted) { + init(size, comparator, keepSorted); +} + +void LArray::init(int size, LComparator* comparator, BOOL keepSorted) { + mKeepSorted = keepSorted; + mOwnsComparator = true; + if (!comparator) { + mComparator = LDefaultComparator::GetComparator(); + mOwnsComparator = false; + } else { + mComparator = comparator; + } + mItemSize = size; + mItemCount = 0; + mExpandSize = 10; + mBuffer = malloc(mExpandSize * mItemSize); +} + +LArray::~LArray() { + if (mComparator && mOwnsComparator) + delete mComparator; + free(mBuffer); +} + +/*virtual*/ int LArray::GetCount() const { + return mItemCount; +} + +void LArray::Expand(int amount) { + int threshold = mItemCount + amount; + if (threshold > mExpandSize) { + mExpandSize = threshold + 10; + mBuffer = realloc(mBuffer, mExpandSize * mItemSize); + } + mItemCount += amount; +} + +void LArray::AdjustAllocation(int amount) { + if (amount > mExpandSize) { + mExpandSize = amount + 10; + mBuffer = realloc(mBuffer, mExpandSize * mItemSize); + } +} + +void LArray::SetKeepSorted(int keepSorted) { + mKeepSorted = keepSorted; +} + +/*virtual*/ void LArray::InsertItemsAt(int count, int where, const void* data) { + if (!mKeepSorted) { + if (where == 0) + where = 1; + + int oldCount = mItemCount; + Expand(count); + memmove( + (char *) mBuffer + mItemSize * (where - 1 + count), + (char *) mBuffer + mItemSize * (where - 1), + mItemSize * (oldCount - (where - 1)) + ); + + if (data) { + for (int i = 0; i < count; i++) { + memcpy((char *) mBuffer + mItemSize * (where - 1 + i), data, mItemSize); + } + } + } else { + for (int i = 0; i < count; i++) { + Add((const char *) data + i * mItemSize); + } + } +} + +/*virtual*/ void LArray::RemoveItemsAt(int count, int where) { +#line 94 + _ASSERT(where > 0); + + if (where < (mItemCount + 1)) { + memmove( + (char *) mBuffer + mItemSize * (where - 1), + (char *) mBuffer + mItemSize * (where - 1 + count), + mItemSize * (mItemCount - (where - 1 + count)) + ); + } + + mItemCount -= count; +} + +/*virtual*/ void LArray::Remove(const void* item) { + int index = FetchIndexOf(item); + if (index != 0) + RemoveItemsAt(1, index); +} + +/*virtual*/ int LArray::FetchIndexOf(const void* item) const { + char *p = (char *) mBuffer; + for (int i = 0; i < mItemCount; i++) { + if (memcmp(p, item, mItemSize) == 0) + return i + 1; + p += mItemSize; + } + return 0; +} + +/*virtual*/ int LArray::FetchItemAt(int index, void* outItem) const { +#line 123 + _ASSERT(index > 0); + + if (index > mItemCount) + return false; + + memcpy(outItem, (char *) mBuffer + mItemSize * (index - 1), mItemSize); + return true; +} + +/*virtual*/ void LArray::AssignItemsAt(int count, int where, void* data) { + if (!mKeepSorted) { +#line 134 + _ASSERT(where > 0); + + if ((where - 1 + count) > mItemCount) + Expand((where - 1 + count) - mItemCount); + + if (data) { + for (int i = 0; i < count; i++) { + memcpy((char *) mBuffer + mItemSize * (where - 1 + i), data, mItemSize); + } + } + } else { + if ((where - 1 + count) > mItemCount) + Expand((where - 1 + count) - mItemCount); + + RemoveItemsAt(count, where); + InsertItemsAt(count, where, data); + } +} + +/*virtual*/ void LArray::Add(const void* item) { + if (!mKeepSorted) { + Expand(1); + memcpy((char *) mBuffer + mItemSize * (mItemCount - 1), item, mItemSize); + } else { + char *p = (char *) mBuffer; + int i; + + for (i = 0; i < mItemCount; i++) { + if (mComparator->Compare(item, p, mItemSize, mItemSize) < 0) { + mKeepSorted = false; + InsertItemsAt(1, i + 1, item); + mKeepSorted = true; + break; + } + p += mItemSize; + } + + if (i == mItemCount) { + mKeepSorted = false; + Add(item); + mKeepSorted = true; + } + } +} + +void LArray::SetComparator(LComparator* comparator) { + if (mComparator && mOwnsComparator) + delete mComparator; + mComparator = comparator; +} + +/*virtual*/ void LArray::ReadAsWord(T2Archive& archive) { + int itemSize; + int count; + int i; + unsigned char zero; + int totalSize; + unsigned short item; + + archive >> itemSize; + archive >> count; + archive >> i; + archive >> i; + archive >> zero; + archive >> zero; + archive >> totalSize; + + if (mItemCount > 0) + RemoveItemsAt(mItemCount, 1); + + for (i = 0; i < count; i++) { + archive >> item; + unsigned int v = item; + Add(&v); + } + + for (; i < totalSize / itemSize; i++) { + archive >> item; + } +} + +/*virtual*/ void LArray::WriteAsWord(T2Archive& archive) { + int boop = 2; + archive << boop; + + boop = mItemCount; + archive << boop; + + int byteCount = boop * 2; + archive << byteCount; + archive << byteCount; + + unsigned char zero = 0; + archive << zero; + + zero = 0; + archive << zero; + + int totalSize = mItemCount * 2; + archive << totalSize; + + LArrayIterator iter(*this); + unsigned int item; + while (iter.Next(&item)) { + unsigned short v = item; + archive << v; + } +} + +/*virtual*/ void LArray::ReadAsDWord(T2Archive& archive) { + unsigned long code; + archive >> code; +#line 261 + _ASSERT(code == 'Darr'); + + if (mItemCount > 0) + RemoveItemsAt(mItemCount, 1); + + int count; + archive >> count; + + unsigned int item; + for (int i = 0; i < count; i++) { + archive >> item; + Add(&item); + } +} + +/*virtual*/ void LArray::ReadAsChar(T2Archive& archive) { + if (mItemCount > 0) + RemoveItemsAt(mItemCount, 1); + + int i; + int elemSize; + int elemCount; + int byteCount; + int byteCount2; + int totalSize; + unsigned char buf; + + archive >> elemSize; + archive >> elemCount; + archive >> byteCount; + archive >> byteCount2; + archive >> totalSize; + + for (i = 0; i < elemCount; i++) { + archive >> buf; + Add(&buf); + } + for (; i < totalSize; i++) { + archive >> buf; + } +} + +/*virtual*/ void LArray::WriteAsDWord(T2Archive& archive) { + unsigned long code = 'Darr'; + archive << code; + archive << mItemCount; + + LArrayIterator iter(*this); + unsigned int item; + while (iter.Next(&item)) { + archive << item; + } +} + +/*virtual*/ void LArray::WriteAsChar(T2Archive& archive) { + int elemSize = 1; + int byteCount = mItemCount; + int byteCount2 = byteCount; + int totalSize = byteCount; + + archive << elemSize; + archive << mItemCount; + archive << byteCount; + archive << byteCount2; + archive << totalSize; + + LArrayIterator iter(*this); + unsigned char item; + while (iter.Next(&item)) { + archive << item; + } +} + +LArrayIterator::LArrayIterator(const LArray& array, int index) { + mArray = &array; + mNextIndex = index; +} + +LArrayIterator::LArrayIterator(const LArrayIterator& iter) { + mArray = iter.mArray; + mNextIndex = iter.mNextIndex; +} + +LArrayIterator::~LArrayIterator() { +} + +void LArrayIterator::ResetTo(int index) { +#line 366 + _ASSERT(index == 0 || index == 1); + mNextIndex = 1; +} + +void LArrayIterator::Rewind() { + mNextIndex = 1; +} + +void LArrayIterator::Seek(const LArrayIterator& iter) { + mArray = iter.mArray; + mNextIndex = iter.mNextIndex; +} + +BOOL LArrayIterator::Next(void* item) { + if (mNextIndex > mArray->GetCount()) { + mCurrentIndex = 0; + return false; + } else { + mArray->FetchItemAt(mNextIndex, item); + mCurrentIndex = mNextIndex; + mNextIndex++; + return true; + } +} + +BOOL LArrayIterator::Previous(void* item) { + mCurrentIndex = mNextIndex; + mNextIndex--; + if (mNextIndex < 1) { + mCurrentIndex = 0; + return false; + } else { + mArray->FetchItemAt(mNextIndex, item); + return true; + } +} + + + +LDefaultComparator* LDefaultComparator::sDefaultComparator; + +/*virtual*/ int LDefaultComparator::Compare(const void* inItemOne, const void* inItemTwo, unsigned int inSizeOne, unsigned int inSizeTwo) const { + int result = memcmp(inItemOne, inItemTwo, (inSizeOne < inSizeTwo) ? inSizeOne : inSizeTwo); + if (result == 0) + result = inSizeOne - inSizeTwo; + return result; +} + +/*virtual*/ BOOL LDefaultComparator::IsEqualTo(const void* inItemOne, const void* inItemTwo, unsigned int inSizeOne, unsigned int inSizeTwo) const { + if (inSizeOne != inSizeTwo) { + return 0; + } else { + return memcmp(inItemOne, inItemTwo, inSizeOne) == 0; + } +} + +LDefaultComparator* LDefaultComparator::GetComparator() { + if (!sDefaultComparator) + sDefaultComparator = new LDefaultComparator; + return sDefaultComparator; +} + +LDefaultComparator::LDefaultComparator() { +} + +/*virtual*/ LDefaultComparator::~LDefaultComparator() { +} |