Add resizearray for assoc arrays
This commit is contained in:
parent
517deb57e6
commit
bb37025026
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue