1
0
Fork 0

Codechange: Move NewGRF ByteReader to own file.

pull/13879/head
Peter Nelson 2025-03-21 19:55:31 +00:00 committed by Peter Nelson
parent 84f785b06b
commit fe9dfa2b08
5 changed files with 163 additions and 96 deletions

View File

@ -17,6 +17,7 @@ add_subdirectory(linkgraph)
add_subdirectory(misc)
add_subdirectory(music)
add_subdirectory(network)
add_subdirectory(newgrf)
add_subdirectory(os)
add_subdirectory(pathfinder)
add_subdirectory(saveload)

View File

@ -54,6 +54,7 @@
#include "vehicle_base.h"
#include "road.h"
#include "newgrf_roadstop.h"
#include "newgrf/newgrf_bytereader.h"
#include "table/strings.h"
#include "table/build_industry.h"
@ -213,102 +214,6 @@ static inline bool IsValidNewGRFImageIndex(uint8_t image_index)
return image_index == 0xFD || IsValidImageIndex<T>(image_index);
}
class OTTDByteReaderSignal { };
/** Class to read from a NewGRF file */
class ByteReader {
protected:
uint8_t *data;
uint8_t *end;
public:
ByteReader(uint8_t *data, uint8_t *end) : data(data), end(end) { }
inline uint8_t *ReadBytes(size_t size)
{
if (data + size >= end) {
/* Put data at the end, as would happen if every byte had been individually read. */
data = end;
throw OTTDByteReaderSignal();
}
uint8_t *ret = data;
data += size;
return ret;
}
inline uint8_t ReadByte()
{
if (data < end) return *(data)++;
throw OTTDByteReaderSignal();
}
uint16_t ReadWord()
{
uint16_t val = ReadByte();
return val | (ReadByte() << 8);
}
uint16_t ReadExtendedByte()
{
uint16_t val = ReadByte();
return val == 0xFF ? ReadWord() : val;
}
uint32_t ReadDWord()
{
uint32_t val = ReadWord();
return val | (ReadWord() << 16);
}
uint32_t PeekDWord()
{
AutoRestoreBackup backup(this->data, this->data);
return this->ReadDWord();
}
uint32_t ReadVarSize(uint8_t size)
{
switch (size) {
case 1: return ReadByte();
case 2: return ReadWord();
case 4: return ReadDWord();
default:
NOT_REACHED();
return 0;
}
}
std::string_view ReadString()
{
char *string = reinterpret_cast<char *>(data);
size_t string_length = ttd_strnlen(string, Remaining());
/* Skip past the terminating NUL byte if it is present, but not more than remaining. */
Skip(std::min(string_length + 1, Remaining()));
return std::string_view(string, string_length);
}
inline size_t Remaining() const
{
return end - data;
}
inline bool HasData(size_t count = 1) const
{
return data + count <= end;
}
inline void Skip(size_t len)
{
data += len;
/* It is valid to move the buffer to exactly the end of the data,
* as there may not be any more data read. */
if (data > end) throw OTTDByteReaderSignal();
}
};
typedef void (*SpecialSpriteHandler)(ByteReader &buf);
/** The maximum amount of stations a single GRF is allowed to add */

View File

@ -0,0 +1,4 @@
add_files(
newgrf_bytereader.cpp
newgrf_bytereader.h
)

View File

@ -0,0 +1,57 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file newgrf_bytereader.cpp NewGRF byte buffer reader implementation. */
#include "../stdafx.h"
#include "../core/backup_type.hpp"
#include "../string_func.h"
#include "newgrf_bytereader.h"
#include "../safeguards.h"
/**
* Read a single DWord (32 bits).
* @note The buffer is NOT advanced.
* @returns Value read from buffer.
*/
uint32_t ByteReader::PeekDWord()
{
AutoRestoreBackup backup(this->data, this->data);
return this->ReadDWord();
}
/**
* Read a value of the given number of bytes.
* @returns Value read from buffer.
*/
uint32_t ByteReader::ReadVarSize(uint8_t size)
{
switch (size) {
case 1: return this->ReadByte();
case 2: return this->ReadWord();
case 4: return this->ReadDWord();
default:
NOT_REACHED();
return 0;
}
}
/**
* Read a string.
* @returns Sting read from the buffer.
*/
std::string_view ByteReader::ReadString()
{
const char *string = reinterpret_cast<const char *>(this->data);
size_t string_length = ttd_strnlen(string, this->Remaining());
/* Skip past the terminating NUL byte if it is present, but not more than remaining. */
this->Skip(std::min(string_length + 1, this->Remaining()));
return std::string_view(string, string_length);
}

View File

@ -0,0 +1,100 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file newgrf_bytereader.h NewGRF buffer reader definition. */
#ifndef NEWGRF_BYTEREADER_H
#define NEWGRF_BYTEREADER_H
class OTTDByteReaderSignal { };
/** Class to read from a NewGRF file */
class ByteReader {
public:
ByteReader(const uint8_t *data, const uint8_t *end) : data(data), end(end) { }
const uint8_t *ReadBytes(size_t size)
{
if (this->data + size >= this->end) {
/* Put data at the end, as would happen if every byte had been individually read. */
this->data = this->end;
throw OTTDByteReaderSignal();
}
const uint8_t *ret = this->data;
this->data += size;
return ret;
}
/**
* Read a single byte (8 bits).
* @return Value read from buffer.
*/
uint8_t ReadByte()
{
if (this->data < this->end) return *this->data++;
throw OTTDByteReaderSignal();
}
/**
* Read a single Word (16 bits).
* @return Value read from buffer.
*/
uint16_t ReadWord()
{
uint16_t val = this->ReadByte();
return val | (this->ReadByte() << 8);
}
/**
* Read a single Extended Byte (8 or 16 bits).
* @return Value read from buffer.
*/
uint16_t ReadExtendedByte()
{
uint16_t val = this->ReadByte();
return val == 0xFF ? this->ReadWord() : val;
}
/**
* Read a single DWord (32 bits).
* @return Value read from buffer.
*/
uint32_t ReadDWord()
{
uint32_t val = this->ReadWord();
return val | (this->ReadWord() << 16);
}
uint32_t PeekDWord();
uint32_t ReadVarSize(uint8_t size);
std::string_view ReadString();
size_t Remaining() const
{
return this->end - this->data;
}
bool HasData(size_t count = 1) const
{
return this->data + count <= this->end;
}
void Skip(size_t len)
{
this->data += len;
/* It is valid to move the buffer to exactly the end of the data,
* as there may not be any more data read. */
if (this->data > this->end) throw OTTDByteReaderSignal();
}
private:
const uint8_t *data; ///< Current position within data.
const uint8_t *end; ///< Last position of data.
};
#endif /* NEWGRF_BYTEREADER_H */