Add resizearray for assoc arrays

This commit is contained in:
Vasilii Rogin 2023-04-23 20:29:45 +03:00
parent 517deb57e6
commit bb37025026
3 changed files with 95 additions and 8 deletions

View File

@ -2,6 +2,7 @@
#include "interpreter.h" #include "interpreter.h"
#include "sfall_script_value.h" #include "sfall_script_value.h"
#include <algorithm>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <memory> #include <memory>
@ -17,6 +18,31 @@ static ArrayId stackArrayId = 1;
#define ARRAY_MAX_STRING (255) // maximum length of string to be stored as array key or value #define ARRAY_MAX_STRING (255) // maximum length of string to be stored as array key or value
#define ARRAY_MAX_SIZE (100000) // maximum number of array elements, #define ARRAY_MAX_SIZE (100000) // maximum number of array elements,
// special actions for arrays using array_resize operator
#define ARRAY_ACTION_SORT (-2)
#define ARRAY_ACTION_RSORT (-3)
#define ARRAY_ACTION_REVERSE (-4)
#define ARRAY_ACTION_SHUFFLE (-5)
template <class T>
static void ListSort(std::vector<T>& arr, int type)
{
switch (type) {
case ARRAY_ACTION_SORT: // sort ascending
std::sort(arr.begin(), arr.end());
break;
case ARRAY_ACTION_RSORT: // sort descending
std::sort(arr.rbegin(), arr.rend());
break;
case ARRAY_ACTION_REVERSE: // reverse elements
std::reverse(arr.rbegin(), arr.rend());
break;
case ARRAY_ACTION_SHUFFLE: // shuffle elements
std::random_shuffle(arr.rbegin(), arr.rend());
break;
}
}
class SFallArray { class SFallArray {
protected: protected:
uint32_t mFlags; uint32_t mFlags;
@ -26,6 +52,7 @@ public:
virtual ProgramValue GetArrayKey(int index) = 0; virtual ProgramValue GetArrayKey(int index) = 0;
virtual ProgramValue GetArray(const SFallScriptValue& key) = 0; virtual ProgramValue GetArray(const SFallScriptValue& key) = 0;
virtual void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) = 0; virtual void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) = 0;
virtual void ResizeArray(int newLen) = 0;
}; };
class SFallArrayList : public SFallArray { class SFallArrayList : public SFallArray {
@ -71,9 +98,6 @@ public:
void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset)
{ {
// TODO: assoc
if (key.isInt()) { if (key.isInt()) {
auto index = key.asInt(); auto index = key.asInt();
if (index >= 0 && index < size()) { if (index >= 0 && index < size()) {
@ -81,6 +105,27 @@ public:
} }
} }
} }
void ResizeArray(int newLen)
{
if (newLen == -1 || size() == newLen) {
return;
};
if (newLen == 0) {
values.clear();
} else if (newLen > 0) {
if (newLen > ARRAY_MAX_SIZE) newLen = ARRAY_MAX_SIZE; // safety
std::vector<SFallScriptValue> newValues;
newValues.reserve(newLen);
for (size_t i = 0; i < std::min(newLen, size()); i++) {
newValues.push_back(values[i]);
};
values = newValues;
} else if (newLen >= ARRAY_ACTION_SHUFFLE) {
ListSort(values, newLen);
}
}
}; };
class SFallArrayAssoc : public SFallArray { class SFallArrayAssoc : public SFallArray {
@ -160,9 +205,35 @@ public:
} }
} }
} }
void ResizeArray(int newLen)
{
if (newLen == -1 || size() == newLen) {
return;
};
// only allow to reduce number of elements (adding range of elements is meaningless for maps)
if (newLen >= 0 && newLen < size()) {
std::vector<SFallScriptValue> newKeys;
newKeys.reserve(newLen);
for (size_t i = 0; i < newLen; i++) {
newKeys[i] = keys[i];
};
for (size_t i = newLen; i < size(); i++) {
map.erase(keys[i]);
};
keys = newKeys;
} else if (newLen < 0) {
if (newLen < (ARRAY_ACTION_SHUFFLE - 2)) return;
// TODO
// MapSort(arr, newlen);
}
};
}; };
using ArraysMap = std::unordered_map<ArrayId, std::unique_ptr<SFallArray>>; using ArraysMap
= std::unordered_map<ArrayId, std::unique_ptr<SFallArray>>;
ArraysMap arrays; ArraysMap arrays;
std::unordered_set<ArrayId> temporaryArrays; std::unordered_set<ArrayId> temporaryArrays;
@ -215,15 +286,11 @@ int LenArray(ArrayId array_id)
return -1; return -1;
}; };
// TODO: assoc
return arr->size(); return arr->size();
} }
ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key) ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key)
{ {
// TODO: If type is string then do substr
auto& arr = arrays[array_id]; auto& arr = arrays[array_id];
if (!arr) { if (!arr) {
@ -270,4 +337,12 @@ void sfallArraysReset()
stackArrayId = 1; stackArrayId = 1;
} }
void ResizeArray(ArrayId array_id, int newLen)
{
auto& arr = arrays[array_id];
if (!arr) {
return;
};
arr->ResizeArray(newLen);
}
} }

View File

@ -22,6 +22,7 @@ ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key);
void SetArray(ArrayId array_id, const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset); void SetArray(ArrayId array_id, const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset);
void FreeArray(ArrayId array_id); void FreeArray(ArrayId array_id);
void FixArray(ArrayId id); void FixArray(ArrayId id);
void ResizeArray(ArrayId array_id, int newLen);
void DeleteAllTempArrays(); void DeleteAllTempArrays();
void sfallArraysReset(); void sfallArraysReset();

View File

@ -536,6 +536,8 @@ static void opSetArray(Program* program)
// get_array // get_array
static void opGetArray(Program* program) static void opGetArray(Program* program)
{ {
// TODO: If type is string then do substr instead of array operation
auto key = programStackPopValue(program); auto key = programStackPopValue(program);
auto arrayId = programStackPopInteger(program); auto arrayId = programStackPopInteger(program);
auto value = GetArray(arrayId, SFallScriptValue { key }); auto value = GetArray(arrayId, SFallScriptValue { key });
@ -556,6 +558,14 @@ static void opLenArray(Program* program)
programStackPushInteger(program, LenArray(arrayId)); programStackPushInteger(program, LenArray(arrayId));
} }
// resize_array
static void opResizeArray(Program* program)
{
auto newLen = programStackPopInteger(program);
auto arrayId = programStackPopInteger(program);
ResizeArray(arrayId, newLen);
}
// party_member_list // party_member_list
static void opPartyMemberList(Program* program) static void opPartyMemberList(Program* program)
{ {
@ -707,6 +717,7 @@ void sfallOpcodesInit()
interpreterRegisterOpcode(0x822F, opGetArray); interpreterRegisterOpcode(0x822F, opGetArray);
interpreterRegisterOpcode(0x8230, opFreeArray); interpreterRegisterOpcode(0x8230, opFreeArray);
interpreterRegisterOpcode(0x8231, opLenArray); interpreterRegisterOpcode(0x8231, opLenArray);
interpreterRegisterOpcode(0x8232, opResizeArray);
interpreterRegisterOpcode(0x8233, opTempArray); interpreterRegisterOpcode(0x8233, opTempArray);
interpreterRegisterOpcode(0x8233, opFixArray); interpreterRegisterOpcode(0x8233, opFixArray);
interpreterRegisterOpcode(0x8237, opParseInt); interpreterRegisterOpcode(0x8237, opParseInt);