fallout2-ce/src/sfall_arrays.cc

251 lines
5.6 KiB
C++
Raw Normal View History

2023-04-19 16:23:33 -07:00
#include "sfall_arrays.h"
2023-04-19 13:13:02 -07:00
#include "interpreter.h"
2023-04-19 16:23:33 -07:00
#include "sfall_script_value.h"
2023-04-19 13:13:02 -07:00
#include <cstdint>
2023-04-23 09:48:53 -07:00
#include <map>
2023-04-23 09:31:15 -07:00
#include <memory>
2023-04-19 13:13:02 -07:00
#include <stdexcept>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace fallout {
static ArrayId nextArrayID = 1;
static ArrayId stackArrayId = 1;
#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,
class SFallArray {
2023-04-23 09:41:49 -07:00
protected:
uint32_t mFlags;
2023-04-19 13:13:02 -07:00
public:
2023-04-23 09:41:49 -07:00
virtual int size() = 0;
virtual ProgramValue GetArrayKey(int index) = 0;
virtual ProgramValue GetArray(const SFallScriptValue& key) = 0;
virtual void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) = 0;
};
2023-04-19 13:13:02 -07:00
2023-04-23 09:41:49 -07:00
class SFallArrayList : public SFallArray {
private:
2023-04-23 09:48:53 -07:00
// TODO: SFall copies strings
std::vector<SFallScriptValue> values;
2023-04-23 09:41:49 -07:00
public:
SFallArrayList() = delete;
2023-04-19 13:13:02 -07:00
2023-04-23 09:41:49 -07:00
SFallArrayList(unsigned int len, uint32_t flags)
2023-04-19 13:13:02 -07:00
{
2023-04-20 12:15:00 -07:00
values.resize(len);
2023-04-23 09:41:49 -07:00
mFlags = flags;
2023-04-19 13:13:02 -07:00
}
2023-04-20 10:50:46 -07:00
2023-04-19 15:20:05 -07:00
int size()
{
2023-04-20 12:15:00 -07:00
return values.size();
2023-04-19 15:20:05 -07:00
}
2023-04-23 09:31:15 -07:00
2023-04-23 09:41:49 -07:00
ProgramValue GetArrayKey(int index)
{
if (index < -1 || index > size()) {
return SFallScriptValue(0);
};
if (index == -1) { // special index to indicate if array is associative
throw(std::invalid_argument("Not implemented yet"));
};
// TODO: assoc
return SFallScriptValue(index);
}
ProgramValue GetArray(const SFallScriptValue& key)
{
// TODO assoc
auto element_index = key.asInt();
if (element_index < 0 || element_index >= size()) {
return SFallScriptValue(0);
};
return values[element_index];
}
void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset)
{
// TODO: assoc
if (key.isInt()) {
auto index = key.asInt();
if (index >= 0 && index < size()) {
values[index] = key;
}
}
}
2023-04-19 13:13:02 -07:00
};
2023-04-23 09:48:53 -07:00
class SFallArrayAssoc : public SFallArray {
private:
// TODO: SFall copies strings
std::vector<SFallScriptValue> keys;
std::map<SFallScriptValue, SFallScriptValue> map;
public:
SFallArrayAssoc() = delete;
SFallArrayAssoc(uint32_t flags)
{
mFlags = flags;
}
int size()
{
return keys.size();
}
ProgramValue GetArrayKey(int index)
{
// if (index < -1 || index > size()) {
// return SFallScriptValue(0);
// };
// if (index == -1) { // special index to indicate if array is associative
// throw(std::invalid_argument("Not implemented yet"));
// };
// // TODO: assoc
// return SFallScriptValue(index);
}
ProgramValue GetArray(const SFallScriptValue& key)
{
// TODO assoc
// auto element_index = key.asInt();
// if (element_index < 0 || element_index >= size()) {
// return SFallScriptValue(0);
// };
// return values[element_index];
}
void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset)
{
// TODO: assoc
// if (key.isInt()) {
// auto index = key.asInt();
// if (index >= 0 && index < size()) {
// values[index] = key;
// }
// }
}
};
2023-04-23 09:31:15 -07:00
using ArraysMap = std::unordered_map<ArrayId, std::unique_ptr<SFallArray>>;
2023-04-19 14:58:30 -07:00
ArraysMap arrays;
std::unordered_set<ArrayId> temporaryArrays;
2023-04-19 13:13:02 -07:00
ArrayId CreateArray(int len, uint32_t flags)
{
flags = (flags & ~1); // reset 1 bit
if (len < 0) {
2023-04-19 16:23:33 -07:00
flags |= SFALL_ARRAYFLAG_ASSOC;
2023-04-19 16:51:20 -07:00
// TODO: Implement
2023-04-19 13:13:02 -07:00
throw(std::invalid_argument("Not implemented yet"));
2023-04-23 09:48:53 -07:00
} else if (len > ARRAY_MAX_SIZE) {
2023-04-19 13:13:02 -07:00
len = ARRAY_MAX_SIZE; // safecheck
2023-04-23 09:48:53 -07:00
};
2023-04-19 13:13:02 -07:00
ArrayId array_id = nextArrayID++;
stackArrayId = array_id;
2023-04-23 09:48:53 -07:00
if (flags & SFALL_ARRAYFLAG_ASSOC) {
arrays.emplace(std::make_pair(array_id, std::make_unique<SFallArrayAssoc>(flags)));
} else {
arrays.emplace(std::make_pair(array_id, std::make_unique<SFallArrayList>(len, flags)));
}
2023-04-19 13:13:02 -07:00
return array_id;
}
ArrayId CreateTempArray(int len, uint32_t flags)
{
ArrayId array_id = CreateArray(len, flags);
temporaryArrays.insert(array_id);
return array_id;
}
2023-04-19 15:20:05 -07:00
ProgramValue GetArrayKey(ArrayId array_id, int index)
{
2023-04-23 09:31:15 -07:00
auto& arr = arrays[array_id];
2023-04-23 09:41:49 -07:00
if (!arr) {
2023-04-19 15:39:30 -07:00
return SFallScriptValue(0);
2023-04-19 15:20:05 -07:00
};
2023-04-23 09:41:49 -07:00
return arr->GetArrayKey(index);
2023-04-19 15:20:05 -07:00
}
2023-04-19 15:21:56 -07:00
int LenArray(ArrayId array_id)
{
2023-04-23 09:31:15 -07:00
auto& arr = arrays[array_id];
if (!arr) {
2023-04-19 15:21:56 -07:00
return -1;
};
2023-04-19 16:51:20 -07:00
// TODO: assoc
2023-04-19 15:21:56 -07:00
return arr->size();
}
2023-04-19 16:26:37 -07:00
ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key)
2023-04-19 15:39:30 -07:00
{
2023-04-19 16:49:22 -07:00
// TODO: If type is string then do substr
2023-04-23 09:31:15 -07:00
auto& arr = arrays[array_id];
if (!arr) {
2023-04-19 15:39:30 -07:00
return SFallScriptValue(0);
};
2023-04-23 09:41:49 -07:00
return arr->GetArray(key);
2023-04-19 15:39:30 -07:00
}
2023-04-19 16:23:33 -07:00
void SetArray(ArrayId array_id, const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset)
{
2023-04-23 09:31:15 -07:00
auto& arr = arrays[array_id];
if (!arr) {
2023-04-19 16:23:33 -07:00
return;
2023-04-23 09:31:15 -07:00
}
2023-04-19 16:23:33 -07:00
2023-04-23 09:41:49 -07:00
arr->SetArray(key, val, allowUnset);
2023-04-19 16:23:33 -07:00
}
2023-04-19 16:46:24 -07:00
void FreeArray(ArrayId array_id)
{
// TODO: remove from saved_arrays
arrays.erase(array_id);
}
2023-04-19 16:53:49 -07:00
void FixArray(ArrayId id)
{
temporaryArrays.erase(id);
}
2023-04-19 16:46:24 -07:00
void DeleteAllTempArrays()
{
for (auto it = temporaryArrays.begin(); it != temporaryArrays.end(); ++it) {
FreeArray(*it);
}
temporaryArrays.clear();
}
2023-04-19 23:34:53 -07:00
void sfallArraysReset()
{
temporaryArrays.clear();
arrays.clear();
nextArrayID = 1;
stackArrayId = 1;
}
2023-04-23 09:31:15 -07:00
2023-04-19 13:13:02 -07:00
}