130 lines
3.8 KiB
C++
130 lines
3.8 KiB
C++
#include "ShipLayoutBlueprintSerializer.h"
|
|
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
|
|
#include "toml.hpp"
|
|
|
|
#include "Rotation.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
std::string rotationToString(Rotation r)
|
|
{
|
|
switch (r)
|
|
{
|
|
case Rotation::North: return "north";
|
|
case Rotation::East: return "east";
|
|
case Rotation::South: return "south";
|
|
case Rotation::West: return "west";
|
|
}
|
|
return "north";
|
|
}
|
|
|
|
Rotation parseRotation(const std::string& s)
|
|
{
|
|
if (s == "east") { return Rotation::East; }
|
|
if (s == "south") { return Rotation::South; }
|
|
if (s == "west") { return Rotation::West; }
|
|
return Rotation::North;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace ShipLayoutBlueprintSerializer
|
|
{
|
|
|
|
std::string serialize(const std::vector<ShipLayoutBlueprint>& blueprints)
|
|
{
|
|
toml::array bpArr;
|
|
for (const ShipLayoutBlueprint& bp : blueprints)
|
|
{
|
|
toml::array modArr;
|
|
for (const PlacedModule& pm : bp.modules)
|
|
{
|
|
toml::table modTbl;
|
|
modTbl.insert("type", pm.moduleId);
|
|
modTbl.insert("x", static_cast<int64_t>(pm.position.x()));
|
|
modTbl.insert("y", static_cast<int64_t>(pm.position.y()));
|
|
modTbl.insert("rotation", rotationToString(pm.rotation));
|
|
modArr.push_back(std::move(modTbl));
|
|
}
|
|
|
|
toml::table bpTbl;
|
|
bpTbl.insert("name", bp.name.toStdString());
|
|
bpTbl.insert("ship_type", bp.shipType);
|
|
bpTbl.insert("modules", std::move(modArr));
|
|
bpArr.push_back(std::move(bpTbl));
|
|
}
|
|
|
|
toml::table root;
|
|
root.insert("blueprint", std::move(bpArr));
|
|
|
|
std::ostringstream oss;
|
|
oss << root;
|
|
return oss.str();
|
|
}
|
|
|
|
std::vector<ShipLayoutBlueprint> deserialize(const std::string& tomlContent)
|
|
{
|
|
toml::table root;
|
|
try
|
|
{
|
|
root = toml::parse(tomlContent);
|
|
}
|
|
catch (const toml::parse_error& e)
|
|
{
|
|
std::ostringstream msg;
|
|
msg << "TOML parse error: " << e.description() << " at " << e.source().begin;
|
|
throw std::runtime_error(msg.str());
|
|
}
|
|
|
|
std::vector<ShipLayoutBlueprint> result;
|
|
|
|
const toml::array* bpArr = root["blueprint"].as_array();
|
|
if (!bpArr) { return result; }
|
|
|
|
for (std::size_t i = 0; i < bpArr->size(); ++i)
|
|
{
|
|
const toml::table* bpTbl = (*bpArr)[i].as_table();
|
|
if (!bpTbl) { continue; }
|
|
|
|
const std::optional<std::string> name = (*bpTbl)["name"].value<std::string>();
|
|
const std::optional<std::string> shipType = (*bpTbl)["ship_type"].value<std::string>();
|
|
if (!name || name->empty() || !shipType || shipType->empty()) { continue; }
|
|
|
|
ShipLayoutBlueprint bp;
|
|
bp.name = QString::fromStdString(*name);
|
|
bp.shipType = *shipType;
|
|
|
|
const toml::array* modArr = (*bpTbl)["modules"].as_array();
|
|
if (modArr)
|
|
{
|
|
for (std::size_t j = 0; j < modArr->size(); ++j)
|
|
{
|
|
const toml::table* modTbl = (*modArr)[j].as_table();
|
|
if (!modTbl) { continue; }
|
|
|
|
const std::optional<std::string> type = (*modTbl)["type"].value<std::string>();
|
|
const std::optional<int64_t> x = (*modTbl)["x"].value<int64_t>();
|
|
const std::optional<int64_t> y = (*modTbl)["y"].value<int64_t>();
|
|
const std::optional<std::string> rotStr = (*modTbl)["rotation"].value<std::string>();
|
|
if (!type || !x || !y || !rotStr) { continue; }
|
|
|
|
PlacedModule pm;
|
|
pm.moduleId = *type;
|
|
pm.position = QPoint(static_cast<int>(*x), static_cast<int>(*y));
|
|
pm.rotation = parseRotation(*rotStr);
|
|
bp.modules.push_back(std::move(pm));
|
|
}
|
|
}
|
|
|
|
result.push_back(std::move(bp));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace ShipLayoutBlueprintSerializer
|