126 lines
3.7 KiB
C++
126 lines
3.7 KiB
C++
|
|
#include "Scripting/ScriptFieldStorage.h"
|
||
|
|
|
||
|
|
#include <algorithm>
|
||
|
|
#include <sstream>
|
||
|
|
|
||
|
|
namespace XCEngine {
|
||
|
|
namespace Scripting {
|
||
|
|
|
||
|
|
bool ScriptFieldStorage::SetFieldValue(const std::string& fieldName, ScriptFieldType type, const ScriptFieldValue& value) {
|
||
|
|
if (fieldName.empty() || !IsScriptFieldValueCompatible(type, value)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_fields[fieldName] = StoredScriptField{type, value};
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
const StoredScriptField* ScriptFieldStorage::FindField(const std::string& fieldName) const {
|
||
|
|
const auto it = m_fields.find(fieldName);
|
||
|
|
return it != m_fields.end() ? &it->second : nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
StoredScriptField* ScriptFieldStorage::FindField(const std::string& fieldName) {
|
||
|
|
const auto it = m_fields.find(fieldName);
|
||
|
|
return it != m_fields.end() ? &it->second : nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ScriptFieldStorage::Contains(const std::string& fieldName) const {
|
||
|
|
return m_fields.find(fieldName) != m_fields.end();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ScriptFieldStorage::Remove(const std::string& fieldName) {
|
||
|
|
return m_fields.erase(fieldName) > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ScriptFieldStorage::Clear() {
|
||
|
|
m_fields.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::vector<std::string> ScriptFieldStorage::GetFieldNames() const {
|
||
|
|
std::vector<std::string> names;
|
||
|
|
names.reserve(m_fields.size());
|
||
|
|
for (const auto& entry : m_fields) {
|
||
|
|
names.push_back(entry.first);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::sort(names.begin(), names.end());
|
||
|
|
return names;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string ScriptFieldStorage::SerializeToString() const {
|
||
|
|
std::ostringstream os;
|
||
|
|
const std::vector<std::string> fieldNames = GetFieldNames();
|
||
|
|
|
||
|
|
for (const std::string& fieldName : fieldNames) {
|
||
|
|
const StoredScriptField* field = FindField(fieldName);
|
||
|
|
if (!field) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
os << "field="
|
||
|
|
<< EscapeScriptString(fieldName)
|
||
|
|
<< "|"
|
||
|
|
<< ScriptFieldTypeToString(field->type)
|
||
|
|
<< "|"
|
||
|
|
<< SerializeScriptFieldValue(field->type, field->value)
|
||
|
|
<< "\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
return os.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
void ScriptFieldStorage::DeserializeFromString(const std::string& data) {
|
||
|
|
m_fields.clear();
|
||
|
|
|
||
|
|
std::istringstream input(data);
|
||
|
|
std::string line;
|
||
|
|
while (std::getline(input, line)) {
|
||
|
|
if (line.empty()) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
static constexpr const char* fieldPrefix = "field=";
|
||
|
|
if (line.rfind(fieldPrefix, 0) != 0) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
const std::string payload = line.substr(6);
|
||
|
|
const size_t firstSeparator = payload.find('|');
|
||
|
|
const size_t secondSeparator = payload.find('|', firstSeparator == std::string::npos ? firstSeparator : firstSeparator + 1);
|
||
|
|
|
||
|
|
if (firstSeparator == std::string::npos || secondSeparator == std::string::npos) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
const std::string fieldName = UnescapeScriptString(payload.substr(0, firstSeparator));
|
||
|
|
const std::string typeName = payload.substr(firstSeparator + 1, secondSeparator - firstSeparator - 1);
|
||
|
|
const std::string serializedValue = payload.substr(secondSeparator + 1);
|
||
|
|
|
||
|
|
ScriptFieldType type = ScriptFieldType::None;
|
||
|
|
if (!TryParseScriptFieldType(typeName, type)) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
ScriptFieldValue value = CreateDefaultScriptFieldValue(type);
|
||
|
|
if (!TryDeserializeScriptFieldValue(type, serializedValue, value)) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_fields[fieldName] = StoredScriptField{type, value};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void ScriptFieldStorage::Serialize(std::ostream& os) const {
|
||
|
|
os << SerializeToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
void ScriptFieldStorage::Deserialize(std::istream& is) {
|
||
|
|
std::ostringstream buffer;
|
||
|
|
buffer << is.rdbuf();
|
||
|
|
DeserializeFromString(buffer.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace Scripting
|
||
|
|
} // namespace XCEngine
|