Codechange: Preparation for ChunkHandler subclassing

This commit is contained in:
glx22 2021-06-06 22:26:38 +02:00 committed by Loïc Guilloux
parent 7e7a4aad72
commit f371a5ad70
2 changed files with 99 additions and 32 deletions

View File

@ -314,9 +314,9 @@ static void SlNullPointers()
_sl_version = SAVEGAME_VERSION; _sl_version = SAVEGAME_VERSION;
for (auto &ch : ChunkHandlers()) { for (auto &ch : ChunkHandlers()) {
if (ch.ptrs_proc != nullptr) { if (ch.fix_pointers) {
Debug(sl, 3, "Nulling pointers for {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); Debug(sl, 3, "Nulling pointers for {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id);
ch.ptrs_proc(); ch.FixPointers();
} }
} }
@ -2114,6 +2114,48 @@ void SlAutolength(AutolengthProc *proc, void *arg)
if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size"); if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
} }
void ChunkHandler::Save() const
{
assert(this->save_proc != nullptr);
this->save_proc();
}
void ChunkHandler::Load() const
{
assert(this->load_proc != nullptr);
this->load_proc();
}
void ChunkHandler::FixPointers() const
{
assert(this->ptrs_proc != nullptr);
this->ptrs_proc();
}
void ChunkHandler::LoadCheck(size_t len) const
{
if (this->load_check) {
assert(this->load_check_proc != nullptr);
this->load_check_proc();
} else {
switch (_sl.block_mode) {
case CH_TABLE:
case CH_SPARSE_TABLE:
SlTableHeader({});
FALLTHROUGH;
case CH_ARRAY:
case CH_SPARSE_ARRAY:
SlSkipArray();
break;
case CH_RIFF:
SlSkipBytes(len);
break;
default:
NOT_REACHED();
}
}
}
/** /**
* Load a chunk of data (eg vehicles, stations, etc.) * Load a chunk of data (eg vehicles, stations, etc.)
* @param ch The chunkhandler that will be used for the operation * @param ch The chunkhandler that will be used for the operation
@ -2129,7 +2171,7 @@ static void SlLoadChunk(const ChunkHandler &ch)
_sl.expect_table_header = (_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE); _sl.expect_table_header = (_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE);
/* The header should always be at the start. Read the length; the /* The header should always be at the start. Read the length; the
* load_proc() should as first action process the header. */ * Load() should as first action process the header. */
if (_sl.expect_table_header) { if (_sl.expect_table_header) {
SlIterateArray(); SlIterateArray();
} }
@ -2138,12 +2180,12 @@ static void SlLoadChunk(const ChunkHandler &ch)
case CH_TABLE: case CH_TABLE:
case CH_ARRAY: case CH_ARRAY:
_sl.array_index = 0; _sl.array_index = 0;
ch.load_proc(); ch.Load();
if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); if (_next_offs != 0) SlErrorCorrupt("Invalid array length");
break; break;
case CH_SPARSE_TABLE: case CH_SPARSE_TABLE:
case CH_SPARSE_ARRAY: case CH_SPARSE_ARRAY:
ch.load_proc(); ch.Load();
if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); if (_next_offs != 0) SlErrorCorrupt("Invalid array length");
break; break;
case CH_RIFF: case CH_RIFF:
@ -2152,7 +2194,7 @@ static void SlLoadChunk(const ChunkHandler &ch)
len += SlReadUint16(); len += SlReadUint16();
_sl.obj_len = len; _sl.obj_len = len;
endoffs = _sl.reader->GetSize() + len; endoffs = _sl.reader->GetSize() + len;
ch.load_proc(); ch.Load();
if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size"); if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
break; break;
default: default:
@ -2179,9 +2221,8 @@ static void SlLoadCheckChunk(const ChunkHandler &ch)
_sl.expect_table_header = (_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE); _sl.expect_table_header = (_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE);
/* The header should always be at the start. Read the length; the /* The header should always be at the start. Read the length; the
* load_check_proc() should as first action process the header. */ * LoadCheck() should as first action process the header. */
if (_sl.expect_table_header && ch.load_check_proc != nullptr) { if (_sl.expect_table_header) {
/* If load_check_proc() is nullptr, SlSkipArray() will already skip the header. */
SlIterateArray(); SlIterateArray();
} }
@ -2189,19 +2230,11 @@ static void SlLoadCheckChunk(const ChunkHandler &ch)
case CH_TABLE: case CH_TABLE:
case CH_ARRAY: case CH_ARRAY:
_sl.array_index = 0; _sl.array_index = 0;
if (ch.load_check_proc != nullptr) { ch.LoadCheck();
ch.load_check_proc();
} else {
SlSkipArray();
}
break; break;
case CH_SPARSE_TABLE: case CH_SPARSE_TABLE:
case CH_SPARSE_ARRAY: case CH_SPARSE_ARRAY:
if (ch.load_check_proc != nullptr) { ch.LoadCheck();
ch.load_check_proc();
} else {
SlSkipArray();
}
break; break;
case CH_RIFF: case CH_RIFF:
/* Read length */ /* Read length */
@ -2209,11 +2242,7 @@ static void SlLoadCheckChunk(const ChunkHandler &ch)
len += SlReadUint16(); len += SlReadUint16();
_sl.obj_len = len; _sl.obj_len = len;
endoffs = _sl.reader->GetSize() + len; endoffs = _sl.reader->GetSize() + len;
if (ch.load_check_proc) { ch.LoadCheck(len);
ch.load_check_proc();
} else {
SlSkipBytes(len);
}
if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size"); if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
break; break;
default: default:
@ -2233,9 +2262,6 @@ static void SlSaveChunk(const ChunkHandler &ch)
{ {
if (ch.type == CH_READONLY) return; if (ch.type == CH_READONLY) return;
ChunkSaveLoadProc *proc = ch.save_proc;
assert(proc != nullptr);
SlWriteUint32(ch.id); SlWriteUint32(ch.id);
Debug(sl, 2, "Saving chunk {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); Debug(sl, 2, "Saving chunk {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id);
@ -2246,19 +2272,19 @@ static void SlSaveChunk(const ChunkHandler &ch)
switch (_sl.block_mode) { switch (_sl.block_mode) {
case CH_RIFF: case CH_RIFF:
proc(); ch.Save();
break; break;
case CH_TABLE: case CH_TABLE:
case CH_ARRAY: case CH_ARRAY:
_sl.last_array_index = 0; _sl.last_array_index = 0;
SlWriteByte(_sl.block_mode); SlWriteByte(_sl.block_mode);
proc(); ch.Save();
SlWriteArrayLength(0); // Terminate arrays SlWriteArrayLength(0); // Terminate arrays
break; break;
case CH_SPARSE_TABLE: case CH_SPARSE_TABLE:
case CH_SPARSE_ARRAY: case CH_SPARSE_ARRAY:
SlWriteByte(_sl.block_mode); SlWriteByte(_sl.block_mode);
proc(); ch.Save();
SlWriteArrayLength(0); // Terminate arrays SlWriteArrayLength(0); // Terminate arrays
break; break;
default: NOT_REACHED(); default: NOT_REACHED();
@ -2326,9 +2352,9 @@ static void SlFixPointers()
_sl.action = SLA_PTRS; _sl.action = SLA_PTRS;
for (auto &ch : ChunkHandlers()) { for (auto &ch : ChunkHandlers()) {
if (ch.ptrs_proc != nullptr) { if (ch.fix_pointers) {
Debug(sl, 3, "Fixing pointers for {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); Debug(sl, 3, "Fixing pointers for {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id);
ch.ptrs_proc(); ch.FixPointers();
} }
} }

View File

@ -407,6 +407,47 @@ struct ChunkHandler {
ChunkSaveLoadProc *ptrs_proc; ///< Manipulate pointers in the chunk. ChunkSaveLoadProc *ptrs_proc; ///< Manipulate pointers in the chunk.
ChunkSaveLoadProc *load_check_proc; ///< Load procedure for game preview. ChunkSaveLoadProc *load_check_proc; ///< Load procedure for game preview.
ChunkType type; ///< Type of the chunk. @see ChunkType ChunkType type; ///< Type of the chunk. @see ChunkType
bool fix_pointers = false;
bool load_check = false;
ChunkHandler(uint32 id, ChunkType type) : id(id), type(type) {}
ChunkHandler(uint32 id, ChunkSaveLoadProc *save_proc, ChunkSaveLoadProc *load_proc, ChunkSaveLoadProc *ptrs_proc, ChunkSaveLoadProc *load_check_proc, ChunkType type)
: id(id), save_proc(save_proc), load_proc(load_proc), ptrs_proc(ptrs_proc), load_check_proc(load_check_proc), type(type)
{
this->fix_pointers = ptrs_proc != nullptr;
this->load_check = load_check_proc != nullptr;
}
virtual ~ChunkHandler() {}
/**
* Save the chunk.
* Must be overridden, unless Chunk type is CH_READONLY.
*/
virtual void Save() const;
/**
* Load the chunk.
* Must be overridden.
*/
virtual void Load() const;
/**
* Fix the pointers.
* Pointers are saved using the index of the pointed object.
* On load, pointers are filled with indices and need to be fixed to point to the real object.
* Must be overridden if the chunk saves any pointer.
*/
virtual void FixPointers() const;
/**
* Load the chunk for game preview.
* Default implementation just skips the data.
* @param len Number of bytes to skip.
*/
virtual void LoadCheck(size_t len = 0) const;
}; };
/** A table of ChunkHandler entries. */ /** A table of ChunkHandler entries. */