summaryrefslogtreecommitdiff
path: root/src/T2DLL/LArray.cpp
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-06-14 00:50:34 +0100
committerAsh Wolf <ninji@wuffs.org>2023-06-14 00:50:34 +0100
commit37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch)
treeeaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/LArray.cpp
downloadt2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz
t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip
initial commit
Diffstat (limited to '')
-rw-r--r--src/T2DLL/LArray.cpp406
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() {
+}