Saveload: Use table format for link graph chunks

This commit is contained in:
Jonathan G Rennison 2024-07-31 18:22:36 +01:00
parent 4a12c79c5c
commit 662cae111c
6 changed files with 226 additions and 144 deletions

View File

@ -382,10 +382,10 @@ public:
protected:
friend class LinkGraph::ConstNode;
friend class LinkGraph::Node;
friend SaveLoadTable GetLinkGraphDesc();
friend SaveLoadTable GetLinkGraphJobDesc();
friend void Save_LinkGraph(LinkGraph &lg);
friend void Load_LinkGraph(LinkGraph &lg);
friend struct LinkGraphNodeStructHandler;
friend struct LinkGraphNonTableHelper;
friend NamedSaveLoadTable GetLinkGraphDesc();
friend NamedSaveLoadTable GetLinkGraphJobDesc();
friend upstream_sl::SaveLoadTable upstream_sl::GetLinkGraphDesc();
friend upstream_sl::SaveLoadTable upstream_sl::GetLinkGraphJobDesc();

View File

@ -128,7 +128,7 @@ private:
typedef std::vector<NodeAnnotation> NodeAnnotationVector;
friend SaveLoadTable GetLinkGraphJobDesc();
friend NamedSaveLoadTable GetLinkGraphJobDesc();
friend upstream_sl::SaveLoadTable upstream_sl::GetLinkGraphJobDesc();
friend void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj);
friend void LinkGraphFixupAfterLoad(bool compression_was_date);

View File

@ -46,7 +46,7 @@ private:
~LinkGraphSchedule();
typedef std::list<LinkGraph *> GraphList;
typedef std::list<std::unique_ptr<LinkGraphJob>> JobList;
friend SaveLoadTable GetLinkGraphScheduleDesc();
friend NamedSaveLoadTable GetLinkGraphScheduleDesc();
friend upstream_sl::SaveLoadTable upstream_sl::GetLinkGraphScheduleDesc();
protected:

View File

@ -183,7 +183,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_NEW_SIGNAL_STYLES, XSCF_NULL, 4, 4, "new_signal_styles", nullptr, nullptr, "XBST,NSID" },
{ XSLFI_NO_TREE_COUNTER, XSCF_IGNORABLE_ALL, 1, 1, "no_tree_counter", nullptr, nullptr, nullptr },
{ XSLFI_TOWN_SETTING_OVERRIDE, XSCF_NULL, 1, 1, "town_setting_override", nullptr, nullptr, nullptr },
{ XSLFI_LINKGRAPH_SPARSE_EDGES, XSCF_NULL, 1, 1, "linkgraph_sparse_edges", nullptr, nullptr, nullptr },
{ XSLFI_LINKGRAPH_SPARSE_EDGES, XSCF_NULL, 2, 2, "linkgraph_sparse_edges", nullptr, nullptr, nullptr },
{ XSLFI_AUX_TILE_LOOP, XSCF_NULL, 1, 1, "aux_tile_loop", nullptr, nullptr, nullptr },
{ XSLFI_NEWGRF_ENTITY_EXTRA, XSCF_NULL, 2, 2, "newgrf_entity_extra", nullptr, nullptr, nullptr },
{ XSLFI_TNNC_CHUNK, XSCF_IGNORABLE_ALL, 0, 1, "tnnc_chunk", nullptr, nullptr, "TNNC" },
@ -220,6 +220,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_TABLE_NEWGRF_SL, XSCF_NULL, 2, 2, "table_newgrf_sl", nullptr, nullptr, nullptr },
{ XSLFI_TABLE_INDUSTRY_SL, XSCF_NULL, 2, 2, "table_industry_sl", nullptr, nullptr, nullptr },
{ XSLFI_TABLE_STATION_SL, XSCF_NULL, 1, 1, "table_station_sl", nullptr, nullptr, nullptr },
{ XSLFI_TABLE_LINKGRAPH_SL, XSCF_NULL, 1, 1, "table_linkgraph_sl", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr }, // This is the end marker
};

View File

@ -176,6 +176,7 @@ enum SlXvFeatureIndex {
///< v2: INDY
XSLFI_TABLE_STATION_SL, ///< Use table format for station chunks:
///< v1: STNN
XSLFI_TABLE_LINKGRAPH_SL, ///< Use table format for link graph chunks:
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk

View File

@ -21,23 +21,153 @@ typedef LinkGraph::BaseNode Node;
typedef LinkGraph::BaseEdge Edge;
static uint16_t _num_nodes;
static uint16_t _to_node;
/* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
/**
* SaveLoad desc for a link graph edge.
*/
static const NamedSaveLoad _edge_desc[] = {
NSLT("to", SLTAG(SLTAG_CUSTOM_0, SLEG_VAR(_to_node, SLE_UINT16))),
NSL("", SLE_CONDNULL(4, SL_MIN_VERSION, SLV_191)), // distance
NSL("capacity", SLE_VAR(Edge, capacity, SLE_UINT32)),
NSL("usage", SLE_VAR(Edge, usage, SLE_UINT32)),
NSL("travel_time_sum", SLE_CONDVAR_X(Edge, travel_time_sum, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_TRAVEL_TIME))),
NSL("last_unrestricted_update", SLE_VAR(Edge, last_unrestricted_update, SLE_INT32)),
NSL("last_restricted_update", SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION)),
NSL("last_aircraft_update", SLE_CONDVAR_X(Edge, last_aircraft_update, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_AIRCRAFT))),
//SLE_VAR(Edge, next_edge, SLE_UINT16), // Removed since XSLFI_LINKGRAPH_SPARSE_EDGES
};
struct LinkGraphEdgeStructHandler final : public HeaderOnlySaveLoadStructHandler {
NamedSaveLoadTable GetDescription() const override
{
return _edge_desc;
}
};
/**
* SaveLoad desc for a link graph node.
*/
static const NamedSaveLoad _node_desc[] = {
NSL("xy", SLE_CONDVAR(Node, xy, SLE_UINT32, SLV_191, SL_MAX_VERSION)),
NSL("supply", SLE_VAR(Node, supply, SLE_UINT32)),
NSL("demand", SLE_VAR(Node, demand, SLE_UINT32)),
NSL("station", SLE_VAR(Node, station, SLE_UINT16)),
NSL("last_update", SLE_VAR(Node, last_update, SLE_INT32)),
NSLTAG(SLTAG_CUSTOM_0, NSLT_STRUCTLIST<LinkGraphEdgeStructHandler>("edges")),
};
struct LinkGraphNodeStructHandler final : public TypedSaveLoadStructHandler<LinkGraphNodeStructHandler, LinkGraph> {
SaveLoadTable edge_description;
NamedSaveLoadTable GetDescription() const override
{
return _node_desc;
}
void Save(LinkGraph *lg) const override
{
uint16_t size = lg->Size();
SlSetStructListLength(size);
auto edge_iter = lg->edges.begin();
auto edge_end = lg->edges.end();
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg->nodes[from];
SlObjectSaveFiltered(node, this->GetLoadDescription());
auto edge_start = edge_iter;
uint count = 0;
while (edge_iter != edge_end && edge_iter->first.first == from) {
count++;
++edge_iter;
}
SlWriteSimpleGamma(count);
auto edge_end = edge_iter;
for (auto it = edge_start; it != edge_end; ++it) {
SlWriteUint16(it->first.second);
Edge *edge = &it->second;
SlObjectSaveFiltered(edge, this->edge_description);
}
}
}
void Load(LinkGraph *lg) const override
{
uint num_nodes = SlGetStructListLength(UINT16_MAX);
lg->Init(num_nodes);
for (NodeID from = 0; from < num_nodes; ++from) {
Node *node = &lg->nodes[from];
SlObjectLoadFiltered(node, this->GetLoadDescription());
uint num_edges = SlGetStructListLength(UINT16_MAX);
for (uint i = 0; i < num_edges; i++) {
NodeID to = SlReadUint16();
SlObjectLoadFiltered(&lg->edges[std::make_pair(from, to)], this->edge_description);
}
}
}
void LoadedTableDescription() override
{
if (!SlXvIsFeaturePresent(XSLFI_LINKGRAPH_SPARSE_EDGES, 2)) {
SlErrorCorrupt("XSLFI_LINKGRAPH_SPARSE_EDGES v2 unexpectedly not present");
}
assert(!this->table_data.empty() && this->table_data.back().label_tag == SLTAG_CUSTOM_0);
this->edge_description = this->table_data.back().struct_handler->GetLoadDescription();
assert (!this->edge_description.empty() && this->edge_description.front().label_tag == SLTAG_CUSTOM_0);
this->edge_description = this->edge_description.subspan(1);
this->table_data.pop_back();
}
void SavedTableDescription() override
{
if (this->table_data.empty() || this->table_data.back().label_tag != SLTAG_CUSTOM_0) SlErrorCorrupt("Link graph node format not as expected");
this->edge_description = this->table_data.back().struct_handler->GetLoadDescription();
if (this->edge_description.empty() || this->edge_description.front().label_tag != SLTAG_CUSTOM_0) SlErrorCorrupt("Link graph edge format not as expected");
this->edge_description = this->edge_description.subspan(1);
this->table_data.pop_back();
}
};
/**
* Get a SaveLoad array for a link graph.
* @return SaveLoad array for link graph.
*/
SaveLoadTable GetLinkGraphDesc()
NamedSaveLoadTable GetLinkGraphDesc()
{
static const SaveLoad link_graph_desc[] = {
SLE_CONDVAR_X(LinkGraph, last_compression, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 0, 3)),
SLE_CONDVAR_X(LinkGraph, last_compression, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 4, 5)),
SLE_CONDVAR_X(LinkGraph, last_compression, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 6)),
SLEG_VAR(_num_nodes, SLE_UINT16),
SLE_VAR(LinkGraph, cargo, SLE_UINT8),
static const NamedSaveLoad link_graph_desc[] = {
NSL("last_compression", SLE_CONDVAR_X(LinkGraph, last_compression, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 0, 3))),
NSL("last_compression", SLE_CONDVAR_X(LinkGraph, last_compression, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 4, 5))),
NSL("last_compression", SLE_CONDVAR_X(LinkGraph, last_compression, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 6))),
NSL("", SLEG_VAR(_num_nodes, SLE_UINT16)),
NSL("cargo", SLE_VAR(LinkGraph, cargo, SLE_UINT8)),
NSLT_STRUCTLIST<LinkGraphNodeStructHandler>("nodes"),
};
return link_graph_desc;
}
struct LinkGraphJobStructHandler final : public TypedSaveLoadStructHandler<LinkGraphJobStructHandler, LinkGraphJob> {
NamedSaveLoadTable GetDescription() const override
{
return GetLinkGraphDesc();
}
void Save(LinkGraphJob *lgj) const override
{
SlObjectSaveFiltered(const_cast<LinkGraph *>(&lgj->Graph()), this->GetLoadDescription());
}
void Load(LinkGraphJob *lgj) const override
{
SlObjectLoadFiltered(const_cast<LinkGraph *>(&lgj->Graph()), this->GetLoadDescription());
}
};
void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj)
{
lgj->join_tick *= DAY_TICKS;
@ -63,9 +193,9 @@ void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj)
* Of course the settings have to be saved and loaded, too, to avoid desyncs.
* @return Array of SaveLoad structs.
*/
SaveLoadTable GetLinkGraphJobDesc()
NamedSaveLoadTable GetLinkGraphJobDesc()
{
static std::vector<SaveLoad> saveloads;
static std::vector<NamedSaveLoad> saveloads;
/* Build the SaveLoad array on first call and don't touch it later on */
if (saveloads.size() == 0) {
@ -80,17 +210,18 @@ SaveLoadTable GetLinkGraphJobDesc()
address -= offset_gamesettings;
address += offset_component;
}
saveloads.push_back(sl);
saveloads.push_back(NSL(desc->name, sl));
}
const SaveLoad job_desc[] = {
SLE_CONDVAR_X(LinkGraphJob, join_tick, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 0, 4)),
SLE_CONDVAR_X(LinkGraphJob, join_tick, SLE_FILE_I64 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 5, 5)),
SLE_CONDVAR_X(LinkGraphJob, join_tick, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 6)),
SLE_CONDVAR_X(LinkGraphJob, start_tick, SLE_FILE_I32 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 1, 4)),
SLE_CONDVAR_X(LinkGraphJob, start_tick, SLE_FILE_I64 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 5, 5)),
SLE_CONDVAR_X(LinkGraphJob, start_tick, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 6)),
SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
const NamedSaveLoad job_desc[] = {
NSL("join_tick", SLE_CONDVAR_X(LinkGraphJob, join_tick, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 0, 4))),
NSL("join_tick", SLE_CONDVAR_X(LinkGraphJob, join_tick, SLE_FILE_I64 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 5, 5))),
NSL("join_tick", SLE_CONDVAR_X(LinkGraphJob, join_tick, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 6))),
NSL("start_tick", SLE_CONDVAR_X(LinkGraphJob, start_tick, SLE_FILE_I32 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 1, 4))),
NSL("start_tick", SLE_CONDVAR_X(LinkGraphJob, start_tick, SLE_FILE_I64 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 5, 5))),
NSL("start_tick", SLE_CONDVAR_X(LinkGraphJob, start_tick, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE, 6))),
NSL("link_graph.index", SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16)),
NSLT_STRUCT<LinkGraphJobStructHandler>("linkgraph"),
};
for (auto &sld : job_desc) {
@ -105,91 +236,46 @@ SaveLoadTable GetLinkGraphJobDesc()
* Get a SaveLoad array for the link graph schedule.
* @return SaveLoad array for the link graph schedule.
*/
SaveLoadTable GetLinkGraphScheduleDesc()
NamedSaveLoadTable GetLinkGraphScheduleDesc()
{
static const SaveLoad schedule_desc[] = {
SLE_REFLIST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
SLE_REFLIST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB),
static const NamedSaveLoad schedule_desc[] = {
NSL("schedule", SLE_REFLIST(LinkGraphSchedule, schedule, REF_LINK_GRAPH)),
NSL("running", SLE_REFLIST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB)),
};
return schedule_desc;
}
/* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
struct LinkGraphNonTableHelper {
std::vector<SaveLoad> node_desc;
std::vector<SaveLoad> edge_desc;
std::vector<SaveLoad> graph_desc;
/**
* SaveLoad desc for a link graph node.
*/
static const SaveLoad _node_desc[] = {
SLE_CONDVAR(Node, xy, SLE_UINT32, SLV_191, SL_MAX_VERSION),
SLE_VAR(Node, supply, SLE_UINT32),
SLE_VAR(Node, demand, SLE_UINT32),
SLE_VAR(Node, station, SLE_UINT16),
SLE_VAR(Node, last_update, SLE_INT32),
};
/**
* SaveLoad desc for a link graph edge.
*/
static const SaveLoad _edge_desc[] = {
SLE_CONDNULL(4, SL_MIN_VERSION, SLV_191), // distance
SLE_VAR(Edge, capacity, SLE_UINT32),
SLE_VAR(Edge, usage, SLE_UINT32),
SLE_CONDVAR_X(Edge, travel_time_sum, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_TRAVEL_TIME)),
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
SLE_CONDVAR_X(Edge, last_aircraft_update, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_AIRCRAFT)),
// SLE_VAR(Edge, next_edge, SLE_UINT16), // Removed since XSLFI_LINKGRAPH_SPARSE_EDGES
};
std::vector<SaveLoad> _filtered_node_desc;
std::vector<SaveLoad> _filtered_edge_desc;
std::vector<SaveLoad> _filtered_job_desc;
static void FilterDescs()
{
_filtered_node_desc = SlFilterObject(_node_desc);
_filtered_edge_desc = SlFilterObject(_edge_desc);
_filtered_job_desc = SlFilterObject(GetLinkGraphJobDesc());
}
/**
* Save a link graph.
* @param lg Link graph to be saved or loaded.
*/
void Save_LinkGraph(LinkGraph &lg)
{
uint16_t size = lg.Size();
auto edge_iter = lg.edges.begin();
auto edge_end = lg.edges.end();
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg.nodes[from];
SlObjectSaveFiltered(node, _filtered_node_desc);
while (edge_iter != edge_end && edge_iter->first.first == from) {
SlWriteUint16(edge_iter->first.second);
Edge *edge = &edge_iter->second;
SlObjectSaveFiltered(edge, _filtered_edge_desc);
++edge_iter;
}
SlWriteUint16(INVALID_NODE);
void Setup()
{
if (SlXvIsFeaturePresent(XSLFI_LINKGRAPH_SPARSE_EDGES, 2)) SlErrorCorrupt("XSLFI_LINKGRAPH_SPARSE_EDGES v2 should not be present for non-table chunks");
this->node_desc = SlFilterNamedSaveLoadTable(_node_desc);
this->edge_desc = SlFilterNamedSaveLoadTable(_edge_desc);
this->graph_desc = SlFilterNamedSaveLoadTable(GetLinkGraphDesc());
}
}
void Load_LinkGraph(LinkGraph &lg);
};
/**
* Load a link graph.
* @param lg Link graph to be saved or loaded.
*/
void Load_LinkGraph(LinkGraph &lg)
void LinkGraphNonTableHelper::Load_LinkGraph(LinkGraph &lg)
{
uint size = lg.Size();
if (SlXvIsFeaturePresent(XSLFI_LINKGRAPH_SPARSE_EDGES)) {
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg.nodes[from];
SlObjectLoadFiltered(node, _filtered_node_desc);
SlObjectLoadFiltered(node, this->node_desc);
while (true) {
NodeID to = SlReadUint16();
if (to == INVALID_NODE) break;
SlObjectLoadFiltered(&lg.edges[std::make_pair(from, to)], _filtered_edge_desc);
SlObjectLoadFiltered(&lg.edges[std::make_pair(from, to)], this->edge_desc);
}
}
} else if (IsSavegameVersionBefore(SLV_191)) {
@ -199,10 +285,10 @@ void Load_LinkGraph(LinkGraph &lg)
temp_next_edges.resize(size);
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg.nodes[from];
SlObjectLoadFiltered(node, _filtered_node_desc);
SlObjectLoadFiltered(node, this->node_desc);
/* We used to save the full matrix ... */
for (NodeID to = 0; to < size; ++to) {
SlObjectLoadFiltered(&temp_edges[to], _filtered_edge_desc);
SlObjectLoadFiltered(&temp_edges[to], this->edge_desc);
temp_next_edges[to] = SlReadUint16();
}
for (NodeID to = from; to != INVALID_NODE; to = temp_next_edges[to]) {
@ -212,46 +298,28 @@ void Load_LinkGraph(LinkGraph &lg)
} else {
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg.nodes[from];
SlObjectLoadFiltered(node, _filtered_node_desc);
SlObjectLoadFiltered(node, this->node_desc);
/* ... but as that wasted a lot of space we save a sparse matrix now. */
for (NodeID to = from; to != INVALID_NODE;) {
if (to >= size) SlErrorCorrupt("Link graph structure overflow");
SlObjectLoadFiltered(&lg.edges[std::make_pair(from, to)], _filtered_edge_desc);
SlObjectLoadFiltered(&lg.edges[std::make_pair(from, to)], this->edge_desc);
to = SlReadUint16();
}
}
}
}
/**
* Save a link graph job.
* @param lgj LinkGraphJob to be saved.
*/
static void DoSave_LGRJ(LinkGraphJob *lgj)
{
SlObjectSaveFiltered(lgj, _filtered_job_desc);
_num_nodes = lgj->Size();
SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
Save_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
}
/**
* Save a link graph.
* @param lg LinkGraph to be saved.
*/
static void DoSave_LGRP(LinkGraph *lg)
{
_num_nodes = lg->Size();
SlObject(lg, GetLinkGraphDesc());
Save_LinkGraph(*lg);
}
/**
* Load all link graphs.
*/
static void Load_LGRP()
{
FilterDescs();
SaveLoadTableData slt = SlTableHeaderOrRiff(GetLinkGraphDesc());
const bool is_table = SlIsTableChunk();
LinkGraphNonTableHelper helper;
if (!is_table) helper.Setup();
int index;
while ((index = SlIterateArray()) != -1) {
if (!LinkGraph::CanAllocateItem()) {
@ -259,9 +327,11 @@ static void Load_LGRP()
NOT_REACHED();
}
LinkGraph *lg = new (index) LinkGraph();
SlObject(lg, GetLinkGraphDesc());
lg->Init(_num_nodes);
Load_LinkGraph(*lg);
SlObjectLoadFiltered(lg, slt);
if (!is_table) {
lg->Init(_num_nodes);
helper.Load_LinkGraph(*lg);
}
}
}
@ -270,7 +340,12 @@ static void Load_LGRP()
*/
static void Load_LGRJ()
{
FilterDescs();
SaveLoadTableData slt = SlTableHeaderOrRiff(GetLinkGraphJobDesc());
const bool is_table = SlIsTableChunk();
LinkGraphNonTableHelper helper;
if (!is_table) helper.Setup();
int index;
while ((index = SlIterateArray()) != -1) {
if (!LinkGraphJob::CanAllocateItem()) {
@ -278,26 +353,20 @@ static void Load_LGRJ()
NOT_REACHED();
}
LinkGraphJob *lgj = new (index) LinkGraphJob();
SlObjectLoadFiltered(lgj, _filtered_job_desc);
SlObjectLoadFiltered(lgj, slt);
if (SlXvIsFeatureMissing(XSLFI_LINKGRAPH_DAY_SCALE)) {
extern void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj);
GetLinkGraphJobDayLengthScaleAfterLoad(lgj);
}
LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
SlObject(&lg, GetLinkGraphDesc());
lg.Init(_num_nodes);
Load_LinkGraph(lg);
if (!is_table) {
LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
SlObjectLoadFiltered(&lg, helper.graph_desc);
lg.Init(_num_nodes);
helper.Load_LinkGraph(lg);
}
}
}
/**
* Load the link graph schedule.
*/
static void Load_LGRS()
{
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
}
/**
* Spawn the threads for running link graph calculations.
* Has to be done after loading as the cargo classes might have changed.
@ -333,10 +402,11 @@ void AfterLoadLinkGraphs()
*/
static void Save_LGRP()
{
FilterDescs();
SaveLoadTableData slt = SlTableHeader(GetLinkGraphDesc());
for (LinkGraph *lg : LinkGraph::Iterate()) {
SlSetArrayIndex(lg->index);
SlAutolength(DoSave_LGRP, lg);
SlObjectSaveFiltered(lg, slt);
}
}
@ -345,19 +415,28 @@ static void Save_LGRP()
*/
static void Save_LGRJ()
{
FilterDescs();
SaveLoadTableData slt = SlTableHeader(GetLinkGraphJobDesc());
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
SlSetArrayIndex(lgj->index);
SlAutolength(DoSave_LGRJ, lgj);
SlObjectSaveFiltered(lgj, slt);
}
}
/**
* Load the link graph schedule.
*/
static void Load_LGRS()
{
SlLoadTableOrRiffFiltered(GetLinkGraphScheduleDesc(), &LinkGraphSchedule::instance);
}
/**
* Save the link graph schedule.
*/
static void Save_LGRS()
{
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
SlSaveTableObjectChunk(GetLinkGraphScheduleDesc(), &LinkGraphSchedule::instance);
}
/**
@ -365,13 +444,14 @@ static void Save_LGRS()
*/
static void Ptrs_LGRS()
{
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
SaveLoadTableData slt = SlPrepareNamedSaveLoadTableForPtrOrNull(GetLinkGraphScheduleDesc());
SlObjectPtrOrNullFiltered(&LinkGraphSchedule::instance, slt);
}
static const ChunkHandler linkgraph_chunk_handlers[] = {
{ 'LGRP', Save_LGRP, Load_LGRP, nullptr, nullptr, CH_ARRAY },
{ 'LGRJ', Save_LGRJ, Load_LGRJ, nullptr, nullptr, CH_ARRAY },
{ 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_RIFF }
{ 'LGRP', Save_LGRP, Load_LGRP, nullptr, nullptr, CH_TABLE },
{ 'LGRJ', Save_LGRJ, Load_LGRJ, nullptr, nullptr, CH_TABLE },
{ 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_TABLE }
};
extern const ChunkHandlerTable _linkgraph_chunk_handlers(linkgraph_chunk_handlers);