mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Refactored code in Arrays.cpp and fixed save_array() script function.
* related to "corrupted" savegames in #265.
This commit is contained in:
@@ -212,9 +212,11 @@ use macros sort_array, sort_array_reverse, reverse_array, shuffle_array from sfa
|
|||||||
- always returns 0
|
- always returns 0
|
||||||
|
|
||||||
> void save_array(mixed key, int arrayID):
|
> void save_array(mixed key, int arrayID):
|
||||||
|
- makes the array saveable; it will be saved in sfallgv.sav file when saving the game
|
||||||
- arrayID is associated with given "key"
|
- arrayID is associated with given "key"
|
||||||
- array becomes permanent (if it was temporary) and "saved"
|
- array becomes permanent (if it was temporary) and "saved"
|
||||||
- key can be of any type (int, float or string)
|
- key can be of any type (int, float or string)
|
||||||
|
- if you specify 0 as the key for the array ID, it will make the array "unsaved"
|
||||||
|
|
||||||
> int load_array(mixed key):
|
> int load_array(mixed key):
|
||||||
- load array from savegame data by the same key provided in "save_array"
|
- load array from savegame data by the same key provided in "save_array"
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ void SaveGlobals(HANDLE h) {
|
|||||||
static void ClearGlobals() {
|
static void ClearGlobals() {
|
||||||
globalVars.clear();
|
globalVars.clear();
|
||||||
for (array_itr it = arrays.begin(); it != arrays.end(); ++it) {
|
for (array_itr it = arrays.begin(); it != arrays.end(); ++it) {
|
||||||
it->second.clear();
|
it->second.clearArrayVar();
|
||||||
}
|
}
|
||||||
arrays.clear();
|
arrays.clear();
|
||||||
savedArrays.clear();
|
savedArrays.clear();
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ sArrayElement::sArrayElement(const long& other)
|
|||||||
set(other);
|
set(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sArrayElement::clear()
|
void sArrayElement::clearData()
|
||||||
{
|
{
|
||||||
if (strVal && type == DataType::STR) delete[] strVal;
|
if (type == DataType::STR) delete[] strVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sArrayElement::setByType( DWORD val, DataType dataType )
|
void sArrayElement::setByType( DWORD val, DataType dataType )
|
||||||
@@ -64,21 +64,21 @@ void sArrayElement::setByType( DWORD val, DataType dataType )
|
|||||||
|
|
||||||
void sArrayElement::set( long val )
|
void sArrayElement::set( long val )
|
||||||
{
|
{
|
||||||
clear();
|
clearData();
|
||||||
type = DataType::INT;
|
type = DataType::INT;
|
||||||
intVal = val;
|
intVal = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sArrayElement::set( float val )
|
void sArrayElement::set( float val )
|
||||||
{
|
{
|
||||||
clear();
|
clearData();
|
||||||
type = DataType::FLOAT;
|
type = DataType::FLOAT;
|
||||||
floatVal = val;
|
floatVal = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sArrayElement::set( const char* val, int sLen /*= -1*/ )
|
void sArrayElement::set( const char* val, int sLen /*= -1*/ )
|
||||||
{
|
{
|
||||||
clear();
|
clearData();
|
||||||
type = DataType::STR;
|
type = DataType::STR;
|
||||||
if (sLen == -1) sLen = strlen(val);
|
if (sLen == -1) sLen = strlen(val);
|
||||||
if (sLen >= ARRAY_MAX_STRING) sLen = ARRAY_MAX_STRING - 1; // memory safety
|
if (sLen >= ARRAY_MAX_STRING) sLen = ARRAY_MAX_STRING - 1; // memory safety
|
||||||
@@ -90,7 +90,7 @@ void sArrayElement::set( const char* val, int sLen /*= -1*/ )
|
|||||||
|
|
||||||
void sArrayElement::unset()
|
void sArrayElement::unset()
|
||||||
{
|
{
|
||||||
clear();
|
clearData();
|
||||||
type = DataType::NONE;
|
type = DataType::NONE;
|
||||||
len = intVal = 0;
|
len = intVal = 0;
|
||||||
}
|
}
|
||||||
@@ -99,11 +99,11 @@ DWORD sArrayElement::getHashStatic(DWORD value, DataType type) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case DataType::STR: {
|
case DataType::STR: {
|
||||||
const char* str = (const char*)value;
|
const char* str = (const char*)value;
|
||||||
DWORD res = 0;
|
DWORD hash = 0;
|
||||||
for (int i = 0; str[i] != '\0'; i++) {
|
while (*str) {
|
||||||
res = ((res << 5) + res) + str[i];
|
hash = ((hash << 5) + hash) + *str++;
|
||||||
}
|
}
|
||||||
return res;
|
return hash;
|
||||||
}
|
}
|
||||||
case DataType::INT:
|
case DataType::INT:
|
||||||
case DataType::FLOAT:
|
case DataType::FLOAT:
|
||||||
@@ -150,7 +150,14 @@ void sArrayVar::clearRange( int from, int to /*= -1*/ )
|
|||||||
if (to == -1) to = val.size();
|
if (to == -1) to = val.size();
|
||||||
std::vector<sArrayElement>::iterator it, itTo = val.begin() + to;
|
std::vector<sArrayElement>::iterator it, itTo = val.begin() + to;
|
||||||
for (it = val.begin() + from; it < itTo; ++it) {
|
for (it = val.begin() + from; it < itTo; ++it) {
|
||||||
it->clear();
|
it->clearData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sArrayVar::clearAll()
|
||||||
|
{
|
||||||
|
for (auto it = val.begin(); it != val.end(); ++it) {
|
||||||
|
it->clearData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +186,7 @@ bool LoadArrayElement(sArrayElement* el, HANDLE h)
|
|||||||
el->strVal = nullptr;
|
el->strVal = nullptr;
|
||||||
} else {
|
} else {
|
||||||
ReadFile(h, &el->intVal, 4, &unused, 0);
|
ReadFile(h, &el->intVal, 4, &unused, 0);
|
||||||
|
el->len = 0;
|
||||||
}
|
}
|
||||||
return (el->len) ? (unused != el->len) : (unused != 4);
|
return (el->len) ? (unused != el->len) : (unused != 4);
|
||||||
}
|
}
|
||||||
@@ -202,8 +210,8 @@ static long LoadArraysOld(HANDLE h) {
|
|||||||
var.types = new DWORD[var.len];
|
var.types = new DWORD[var.len];
|
||||||
var.data = new char[var.len * var.datalen];
|
var.data = new char[var.len * var.datalen];
|
||||||
|
|
||||||
ReadFile(h, var.types, (4 * var.len), &unused, 0);
|
ReadFile(h, &var.types, (4 * var.len), &unused, 0);
|
||||||
ReadFile(h, var.data, (var.len * var.datalen), &unused, 0);
|
ReadFile(h, &var.data, (var.len * var.datalen), &unused, 0);
|
||||||
|
|
||||||
varN.flags = 0;
|
varN.flags = 0;
|
||||||
varN.val.resize(var.len);
|
varN.val.resize(var.len);
|
||||||
@@ -250,7 +258,6 @@ long LoadArrays(HANDLE h) {
|
|||||||
arrayVar.key.intVal = static_cast<long>(arrayVar.key.type);
|
arrayVar.key.intVal = static_cast<long>(arrayVar.key.type);
|
||||||
arrayVar.key.type = DataType::INT;
|
arrayVar.key.type = DataType::INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadFile(h, &arrayVar.flags, 4, &unused, 0);
|
ReadFile(h, &arrayVar.flags, 4, &unused, 0);
|
||||||
ReadFile(h, &elCount, 4, &unused, 0); // actual number of elements: keys+values
|
ReadFile(h, &elCount, 4, &unused, 0); // actual number of elements: keys+values
|
||||||
if (unused != 4) return -1;
|
if (unused != 4) return -1;
|
||||||
@@ -268,6 +275,7 @@ long LoadArrays(HANDLE h) {
|
|||||||
|
|
||||||
arrays.insert(array_pair(nextArrayID, arrayVar));
|
arrays.insert(array_pair(nextArrayID, arrayVar));
|
||||||
savedArrays[arrayVar.key] = nextArrayID++;
|
savedArrays[arrayVar.key] = nextArrayID++;
|
||||||
|
|
||||||
arrayVar.keyHash.clear();
|
arrayVar.keyHash.clear();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -277,29 +285,29 @@ void SaveArrays(HANDLE h) {
|
|||||||
DWORD elCount, unused, count = 0;
|
DWORD elCount, unused, count = 0;
|
||||||
WriteFile(h, &count, 4, &unused, 0); // this is for backward compatibility with 3.3-
|
WriteFile(h, &count, 4, &unused, 0); // this is for backward compatibility with 3.3-
|
||||||
|
|
||||||
array_itr arIt;
|
array_itr arrayIt;
|
||||||
ArrayKeysMap::iterator it = savedArrays.begin();
|
ArrayKeysMap::iterator it = savedArrays.begin();
|
||||||
while (it != savedArrays.end()) {
|
while (it != savedArrays.end()) {
|
||||||
arIt = arrays.find(it->second);
|
arrayIt = arrays.find(it->second); // check the existence of an array
|
||||||
if (arIt == arrays.end()) {
|
if (arrayIt == arrays.end()) {
|
||||||
savedArrays.erase(it++);
|
it = savedArrays.erase(it); // array is not found, delete it [fix to C++11 https://en.cppreference.com/w/cpp/container/unordered_map/erase]
|
||||||
} else {
|
} else {
|
||||||
++count;
|
++count;
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WriteFile(h, &count, 4, &unused, 0);
|
WriteFile(h, &count, 4, &unused, 0); // count saved arrays
|
||||||
|
if (count == 0) return;
|
||||||
for (it = savedArrays.begin(); it != savedArrays.end(); ++it) {
|
for (it = savedArrays.begin(); it != savedArrays.end(); ++it) {
|
||||||
arIt = arrays.find(it->second);
|
arrayIt = arrays.find(it->second);
|
||||||
if (arIt != arrays.end()) {
|
if (arrayIt != arrays.end()) {
|
||||||
sArrayVar &var = arrays[it->second];
|
sArrayVar &var = arrays[it->second];
|
||||||
SaveArrayElement(&var.key, h);
|
SaveArrayElement(&var.key, h); // type, key/length of key and string of key
|
||||||
WriteFile(h, &var.flags, 4, &unused, 0);
|
WriteFile(h, &var.flags, 4, &unused, 0);
|
||||||
elCount = var.val.size();
|
elCount = var.val.size();
|
||||||
WriteFile(h, &elCount, 4, &unused, 0);
|
WriteFile(h, &elCount, 4, &unused, 0); // number of elements in saved array
|
||||||
for (std::vector<sArrayElement>::iterator it = var.val.begin(); it != var.val.end(); ++it) {
|
for (std::vector<sArrayElement>::iterator vIt = var.val.begin(); vIt != var.val.end(); ++vIt) {
|
||||||
SaveArrayElement(&(*it), h);
|
SaveArrayElement(&(*vIt), h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,7 +379,7 @@ void DESetArray(int id, const DWORD* types, const char* data) {
|
|||||||
TODO: move somewhere else
|
TODO: move somewhere else
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DWORD _stdcall CreateArray(int len, DWORD flags) {
|
DWORD CreateArray(int len, DWORD flags) {
|
||||||
sArrayVar var;
|
sArrayVar var;
|
||||||
var.flags = (flags & 0xFFFFFFFE); // reset 1 bit
|
var.flags = (flags & 0xFFFFFFFE); // reset 1 bit
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
@@ -395,17 +403,17 @@ DWORD _stdcall CreateArray(int len, DWORD flags) {
|
|||||||
return nextArrayID++;
|
return nextArrayID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD _stdcall TempArray(DWORD len, DWORD flags) {
|
DWORD TempArray(DWORD len, DWORD flags) {
|
||||||
DWORD id = CreateArray(len, flags);
|
DWORD id = CreateArray(len, flags);
|
||||||
tempArrays.insert(id);
|
tempArrays.insert(id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stdcall FreeArray(DWORD id) {
|
void FreeArray(DWORD id) {
|
||||||
array_itr it = arrays.find(id);
|
array_itr it = arrays.find(id);
|
||||||
if (it != arrays.end()) {
|
if (it != arrays.end()) {
|
||||||
savedArrays.erase(it->second.key);
|
if (it->second.key.intVal) savedArrays.erase(it->second.key);
|
||||||
it->second.clear();
|
it->second.clearArrayVar();
|
||||||
arrays.erase(id);
|
arrays.erase(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,7 +427,7 @@ void DeleteAllTempArrays() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptValue _stdcall GetArrayKey(DWORD id, int index) {
|
ScriptValue GetArrayKey(DWORD id, int index) {
|
||||||
if (arrays.find(id) == arrays.end() || index < -1 || index > arrays[id].size()) {
|
if (arrays.find(id) == arrays.end() || index < -1 || index > arrays[id].size()) {
|
||||||
return ScriptValue(0);
|
return ScriptValue(0);
|
||||||
}
|
}
|
||||||
@@ -446,7 +454,7 @@ ScriptValue _stdcall GetArrayKey(DWORD id, int index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptValue _stdcall GetArray(DWORD id, const ScriptValue& key) {
|
ScriptValue GetArray(DWORD id, const ScriptValue& key) {
|
||||||
if (arrays.find(id) == arrays.end()) {
|
if (arrays.find(id) == arrays.end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -478,7 +486,7 @@ ScriptValue _stdcall GetArray(DWORD id, const ScriptValue& key) {
|
|||||||
return ScriptValue(0);
|
return ScriptValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stdcall SetArray(DWORD id, const ScriptValue& key, const ScriptValue& val, bool allowUnset) {
|
void SetArray(DWORD id, const ScriptValue& key, const ScriptValue& val, bool allowUnset) {
|
||||||
if (arrays.find(id) == arrays.end()) {
|
if (arrays.find(id) == arrays.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -529,7 +537,7 @@ void _stdcall SetArray(DWORD id, const ScriptValue& key, const ScriptValue& val,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _stdcall LenArray(DWORD id) {
|
int LenArray(DWORD id) {
|
||||||
if (arrays.find(id) == arrays.end()) return -1;
|
if (arrays.find(id) == arrays.end()) return -1;
|
||||||
return arrays[id].size();
|
return arrays[id].size();
|
||||||
}
|
}
|
||||||
@@ -590,12 +598,16 @@ static void MapSort(sArrayVar& arr, int type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long _stdcall ResizeArray(DWORD id, int newlen) {
|
long ResizeArray(DWORD id, int newlen) {
|
||||||
if (newlen == -1 || arrays.find(id) == arrays.end() || arrays[id].size() == newlen) return 0;
|
if (newlen == -1 || arrays.find(id) == arrays.end()) return 0;
|
||||||
|
|
||||||
sArrayVar &arr = arrays[id];
|
sArrayVar &arr = arrays[id];
|
||||||
|
int arrSize = arr.size();
|
||||||
|
if (arrSize == newlen) return 0;
|
||||||
|
|
||||||
if (arr.isAssoc()) {
|
if (arr.isAssoc()) {
|
||||||
// only allow to reduce number of elements (adding range of elements is meaningless for maps)
|
// only allow to reduce number of elements (adding range of elements is meaningless for maps)
|
||||||
if (newlen >= 0 && newlen < arrays[id].size()) {
|
if (newlen >= 0 && newlen < arrSize) {
|
||||||
ArrayKeysMap::iterator itHash;
|
ArrayKeysMap::iterator itHash;
|
||||||
std::vector<sArrayElement>::iterator itVal;
|
std::vector<sArrayElement>::iterator itVal;
|
||||||
int actualLen = newlen * 2;
|
int actualLen = newlen * 2;
|
||||||
@@ -603,7 +615,10 @@ long _stdcall ResizeArray(DWORD id, int newlen) {
|
|||||||
if ((itHash = arr.keyHash.find(*itVal)) != arr.keyHash.end())
|
if ((itHash = arr.keyHash.find(*itVal)) != arr.keyHash.end())
|
||||||
arr.keyHash.erase(itHash);
|
arr.keyHash.erase(itHash);
|
||||||
}
|
}
|
||||||
arr.clearRange(actualLen);
|
if (actualLen == 0)
|
||||||
|
arr.clearAll();
|
||||||
|
else
|
||||||
|
arr.clearRange(actualLen);
|
||||||
arr.val.resize(actualLen);
|
arr.val.resize(actualLen);
|
||||||
} else if (newlen < 0) {
|
} else if (newlen < 0) {
|
||||||
if (newlen < (ARRAY_ACTION_SHUFFLE - 2)) return -1;
|
if (newlen < (ARRAY_ACTION_SHUFFLE - 2)) return -1;
|
||||||
@@ -612,10 +627,12 @@ long _stdcall ResizeArray(DWORD id, int newlen) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (newlen >= 0) { // actual resize
|
if (newlen >= 0) { // actual resize
|
||||||
if (newlen > ARRAY_MAX_SIZE) // safety
|
if (newlen == 0) {
|
||||||
newlen = ARRAY_MAX_SIZE;
|
arr.clearAll();
|
||||||
if (newlen < arr.size())
|
} else {
|
||||||
arr.clearRange(newlen);
|
if (newlen > ARRAY_MAX_SIZE) newlen = ARRAY_MAX_SIZE; // safety
|
||||||
|
if (newlen < arrSize) arr.clearRange(newlen);
|
||||||
|
}
|
||||||
arr.val.resize(newlen);
|
arr.val.resize(newlen);
|
||||||
} else { // special functions for lists...
|
} else { // special functions for lists...
|
||||||
if (newlen < ARRAY_ACTION_SHUFFLE) return -1;
|
if (newlen < ARRAY_ACTION_SHUFFLE) return -1;
|
||||||
@@ -624,11 +641,11 @@ long _stdcall ResizeArray(DWORD id, int newlen) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stdcall FixArray(DWORD id) {
|
void FixArray(DWORD id) {
|
||||||
tempArrays.erase(id);
|
tempArrays.erase(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptValue _stdcall ScanArray(DWORD id, const ScriptValue& val) {
|
ScriptValue ScanArray(DWORD id, const ScriptValue& val) {
|
||||||
if (arrays.find(id) == arrays.end()) {
|
if (arrays.find(id) == arrays.end()) {
|
||||||
return ScriptValue(-1);
|
return ScriptValue(-1);
|
||||||
}
|
}
|
||||||
@@ -652,7 +669,7 @@ ScriptValue _stdcall ScanArray(DWORD id, const ScriptValue& val) {
|
|||||||
return ScriptValue(-1);
|
return ScriptValue(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD _stdcall LoadArray(const ScriptValue& key) {
|
DWORD LoadArray(const ScriptValue& key) {
|
||||||
if (!key.isInt() || key.asInt() != 0) { // returns arrayId by it's key (ignoring int(0) because it is used to "unsave" array)
|
if (!key.isInt() || key.asInt() != 0) { // returns arrayId by it's key (ignoring int(0) because it is used to "unsave" array)
|
||||||
sArrayElement keyEl = sArrayElement(key.rawValue(), key.type());
|
sArrayElement keyEl = sArrayElement(key.rawValue(), key.type());
|
||||||
|
|
||||||
@@ -678,22 +695,29 @@ DWORD _stdcall LoadArray(const ScriptValue& key) {
|
|||||||
return 0; // not found
|
return 0; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stdcall SaveArray(const ScriptValue& key, DWORD id) {
|
void SaveArray(const ScriptValue& key, DWORD id) {
|
||||||
array_itr it = arrays.find(id), it2;
|
array_itr it, itArray = arrays.find(id); // arrayId => arrayVar
|
||||||
if (it != arrays.end()) {
|
if (itArray != arrays.end()) {
|
||||||
if (!key.isInt() || key.asInt() != 0) {
|
if (!key.isInt() || key.asInt() != 0) {
|
||||||
// make array permanent
|
// make array permanent
|
||||||
FixArray(it->first);
|
FixArray(itArray->first);
|
||||||
// if another array is saved under the same key, clear it
|
// if another array is saved under the same key, clear it
|
||||||
ArrayKeysMap::iterator sIt = savedArrays.find(sArrayElement(key.rawValue(), key.type()));
|
ArrayKeysMap::iterator savedIt = savedArrays.find(sArrayElement(key.rawValue(), key.type()));
|
||||||
if (sIt != savedArrays.end() && sIt->second != id && (it2 = arrays.find(sIt->second)) != arrays.end()) {
|
if (savedIt != savedArrays.end()) {
|
||||||
it2->second.key.unset();
|
if (savedIt->second == id) return; // exit, array is already saveable
|
||||||
|
// arrays have different ID, search the ID of the "saved" array in collection of arrays
|
||||||
|
if ((it = arrays.find(savedIt->second)) != arrays.end()) {
|
||||||
|
// array exists, delete key value
|
||||||
|
savedArrays.erase(savedIt); /* added for fix */
|
||||||
|
it->second.key.unset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
it->second.key.setByType(key.rawValue(), key.type());
|
// make "saved" array
|
||||||
savedArrays[it->second.key] = id;
|
itArray->second.key.setByType(key.rawValue(), key.type());
|
||||||
} else { // int(0) is used to "unsave" array without destroying it
|
savedArrays.emplace(itArray->second.key, id); // savedArrays[itArray->second.key] = id;
|
||||||
int num = savedArrays.erase(it->second.key);
|
} else { // key of int(0) is used to "unsave" array without destroying it
|
||||||
it->second.key.unset();
|
savedArrays.erase(itArray->second.key);
|
||||||
|
itArray->second.key.unset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,7 +732,7 @@ void _stdcall SaveArray(const ScriptValue& key, DWORD id) {
|
|||||||
|
|
||||||
Should always return 0!
|
Should always return 0!
|
||||||
*/
|
*/
|
||||||
DWORD _stdcall StackArray(const ScriptValue& key, const ScriptValue& val) {
|
long StackArray(const ScriptValue& key, const ScriptValue& val) {
|
||||||
DWORD id = stackArrayId;
|
DWORD id = stackArrayId;
|
||||||
if (id == 0 || arrays.find(id) == arrays.end()) {
|
if (id == 0 || arrays.find(id) == arrays.end()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
sArrayElement(const long&);
|
sArrayElement(const long&);
|
||||||
|
|
||||||
// free string resource from memory, has to be called manually when deleting element
|
// free string resource from memory, has to be called manually when deleting element
|
||||||
void clear();
|
void clearData();
|
||||||
|
|
||||||
// set* methods will actually COPY strings, use this when acquiring data from the scripting engine
|
// set* methods will actually COPY strings, use this when acquiring data from the scripting engine
|
||||||
void setByType(DWORD val, DataType dataType);
|
void setByType(DWORD val, DataType dataType);
|
||||||
@@ -107,15 +107,16 @@ public:
|
|||||||
ArrayKeysMap keyHash; // key element => element index, for faster lookup
|
ArrayKeysMap keyHash; // key element => element index, for faster lookup
|
||||||
std::vector<sArrayElement> val; // list of values or key=>value pairs (even - keys, odd - values)
|
std::vector<sArrayElement> val; // list of values or key=>value pairs (even - keys, odd - values)
|
||||||
|
|
||||||
|
sArrayVar() : flags(0), key() {}
|
||||||
|
|
||||||
bool isAssoc() const {
|
bool isAssoc() const {
|
||||||
return (flags & ARRAYFLAG_ASSOC);
|
return (flags & ARRAYFLAG_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// logical array size (number of elements for normal arrays; number of key=>value pairs for associative)
|
// logical array size (number of elements for normal arrays; number of key=>value pairs for associative)
|
||||||
int size() const {
|
int size() const {
|
||||||
return isAssoc()
|
size_t sz = val.size();
|
||||||
? val.size() / 2
|
return isAssoc() ? sz / 2 : sz;
|
||||||
: val.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// usefull when filling array from within sfall code (normal lists only)
|
// usefull when filling array from within sfall code (normal lists only)
|
||||||
@@ -125,15 +126,14 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sArrayVar() : flags(0), key() {}
|
|
||||||
|
|
||||||
// free memory used by strings
|
// free memory used by strings
|
||||||
void clear() {
|
void clearArrayVar() {
|
||||||
clearRange(0);
|
clearAll();
|
||||||
key.clear();
|
key.clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearRange(int from, int to = -1);
|
void clearRange(int from, int to = -1);
|
||||||
|
void clearAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
// arrays map: arrayId => arrayVar
|
// arrays map: arrayId => arrayVar
|
||||||
@@ -160,13 +160,13 @@ void DEGetArray(int id, DWORD* types, char* data);
|
|||||||
void DESetArray(int id, const DWORD* types, const char* data);
|
void DESetArray(int id, const DWORD* types, const char* data);
|
||||||
|
|
||||||
// creates new normal (persistent) array. len == -1 specifies associative array (map)
|
// creates new normal (persistent) array. len == -1 specifies associative array (map)
|
||||||
DWORD _stdcall CreateArray(int len, DWORD flags);
|
DWORD CreateArray(int len, DWORD flags);
|
||||||
|
|
||||||
// same as CreateArray, but creates temporary array instead (will die at the end of the frame)
|
// same as CreateArray, but creates temporary array instead (will die at the end of the frame)
|
||||||
DWORD _stdcall TempArray(DWORD len, DWORD flags);
|
DWORD TempArray(DWORD len, DWORD flags);
|
||||||
|
|
||||||
// destroys array
|
// destroys array
|
||||||
void _stdcall FreeArray(DWORD id);
|
void FreeArray(DWORD id);
|
||||||
|
|
||||||
// destroy all temp arrays
|
// destroy all temp arrays
|
||||||
void DeleteAllTempArrays();
|
void DeleteAllTempArrays();
|
||||||
@@ -174,34 +174,34 @@ void DeleteAllTempArrays();
|
|||||||
/*
|
/*
|
||||||
op_get_array_key can be used to iterate over all keys in associative array
|
op_get_array_key can be used to iterate over all keys in associative array
|
||||||
*/
|
*/
|
||||||
ScriptValue _stdcall GetArrayKey(DWORD id, int index);
|
ScriptValue GetArrayKey(DWORD id, int index);
|
||||||
|
|
||||||
// get array element by index (list) or key (map)
|
// get array element by index (list) or key (map)
|
||||||
ScriptValue _stdcall GetArray(DWORD id, const ScriptValue& key);
|
ScriptValue GetArray(DWORD id, const ScriptValue& key);
|
||||||
|
|
||||||
// set array element by index or key
|
// set array element by index or key
|
||||||
void _stdcall SetArray(DWORD id, const ScriptValue& key, const ScriptValue& val, bool allowUnset);
|
void SetArray(DWORD id, const ScriptValue& key, const ScriptValue& val, bool allowUnset);
|
||||||
|
|
||||||
// number of elements in list or pairs in map
|
// number of elements in list or pairs in map
|
||||||
int _stdcall LenArray(DWORD id);
|
int LenArray(DWORD id);
|
||||||
|
|
||||||
// change array size (only works with list)
|
// change array size (only works with list)
|
||||||
long _stdcall ResizeArray(DWORD id, int newlen);
|
long ResizeArray(DWORD id, int newlen);
|
||||||
|
|
||||||
// make temporary array persistent
|
// make temporary array persistent
|
||||||
void _stdcall FixArray(DWORD id);
|
void FixArray(DWORD id);
|
||||||
|
|
||||||
// searches for a given element in array and returns it's index (for list) or key (for map) or int(-1) if not found
|
// searches for a given element in array and returns it's index (for list) or key (for map) or int(-1) if not found
|
||||||
ScriptValue _stdcall ScanArray(DWORD id, const ScriptValue& val);
|
ScriptValue ScanArray(DWORD id, const ScriptValue& val);
|
||||||
|
|
||||||
// get saved array by it's key
|
// get saved array by it's key
|
||||||
DWORD _stdcall LoadArray(const ScriptValue& key);
|
DWORD LoadArray(const ScriptValue& key);
|
||||||
|
|
||||||
// make array saved into the savegame with associated key
|
// make array saved into the savegame with associated key
|
||||||
void _stdcall SaveArray(const ScriptValue& key, DWORD id);
|
void SaveArray(const ScriptValue& key, DWORD id);
|
||||||
|
|
||||||
// special function that powers array expressions
|
// special function that powers array expressions
|
||||||
DWORD _stdcall StackArray(const ScriptValue& key, const ScriptValue& val);
|
long StackArray(const ScriptValue& key, const ScriptValue& val);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ namespace script
|
|||||||
{
|
{
|
||||||
|
|
||||||
void sf_create_array(OpcodeContext& ctx) {
|
void sf_create_array(OpcodeContext& ctx) {
|
||||||
auto arrayId = CreateArray(ctx.arg(0).asInt(), ctx.arg(1).asInt());
|
auto arrayId = CreateArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
||||||
ctx.setReturn(arrayId, DataType::INT);
|
ctx.setReturn(arrayId, DataType::INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_set_array(OpcodeContext& ctx) {
|
void sf_set_array(OpcodeContext& ctx) {
|
||||||
SetArray(
|
SetArray(
|
||||||
ctx.arg(0).asInt(),
|
ctx.arg(0).rawValue(),
|
||||||
ctx.arg(1),
|
ctx.arg(1),
|
||||||
ctx.arg(2),
|
ctx.arg(2),
|
||||||
true
|
true
|
||||||
@@ -65,55 +65,55 @@ void sf_get_array(OpcodeContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sf_free_array(OpcodeContext& ctx) {
|
void sf_free_array(OpcodeContext& ctx) {
|
||||||
FreeArray(ctx.arg(0).asInt());
|
FreeArray(ctx.arg(0).rawValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_len_array(OpcodeContext& ctx) {
|
void sf_len_array(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(
|
ctx.setReturn(
|
||||||
LenArray(ctx.arg(0).asInt())
|
LenArray(ctx.arg(0).rawValue())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_resize_array(OpcodeContext& ctx) {
|
void sf_resize_array(OpcodeContext& ctx) {
|
||||||
if (ResizeArray(ctx.arg(0).asInt(), ctx.arg(1).asInt())) {
|
if (ResizeArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue())) {
|
||||||
ctx.printOpcodeError("%s() - array sorting error.", ctx.getOpcodeName());
|
ctx.printOpcodeError("%s() - array sorting error.", ctx.getOpcodeName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_temp_array(OpcodeContext& ctx) {
|
void sf_temp_array(OpcodeContext& ctx) {
|
||||||
auto arrayId = TempArray(ctx.arg(0).asInt(), ctx.arg(1).asInt());
|
auto arrayId = TempArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
||||||
ctx.setReturn(arrayId, DataType::INT);
|
ctx.setReturn(arrayId, DataType::INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_fix_array(OpcodeContext& ctx) {
|
void sf_fix_array(OpcodeContext& ctx) {
|
||||||
FixArray(ctx.arg(0).asInt());
|
FixArray(ctx.arg(0).rawValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_scan_array(OpcodeContext& ctx) {
|
void sf_scan_array(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(
|
ctx.setReturn(
|
||||||
ScanArray(ctx.arg(0).asInt(), ctx.arg(1))
|
ScanArray(ctx.arg(0).rawValue(), ctx.arg(1))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_save_array(OpcodeContext& ctx) {
|
void sf_save_array(OpcodeContext& ctx) {
|
||||||
SaveArray(ctx.arg(0), ctx.arg(1).asInt());
|
SaveArray(ctx.arg(0), ctx.arg(1).rawValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_load_array(OpcodeContext& ctx) {
|
void sf_load_array(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(
|
ctx.setReturn(
|
||||||
static_cast<int>(LoadArray(ctx.arg(0)))
|
LoadArray(ctx.arg(0))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_get_array_key(OpcodeContext& ctx) {
|
void sf_get_array_key(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(
|
ctx.setReturn(
|
||||||
GetArrayKey(ctx.arg(0).asInt(), ctx.arg(1).asInt())
|
GetArrayKey(ctx.arg(0).rawValue(), ctx.arg(1).rawValue())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_stack_array(OpcodeContext& ctx) {
|
void sf_stack_array(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(
|
ctx.setReturn(
|
||||||
static_cast<int>(StackArray(ctx.arg(0), ctx.arg(1)))
|
StackArray(ctx.arg(0), ctx.arg(1))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user