mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Move NewGRF ByteReader to own file.
parent
84f785b06b
commit
fe9dfa2b08
|
@ -17,6 +17,7 @@ add_subdirectory(linkgraph)
|
||||||
add_subdirectory(misc)
|
add_subdirectory(misc)
|
||||||
add_subdirectory(music)
|
add_subdirectory(music)
|
||||||
add_subdirectory(network)
|
add_subdirectory(network)
|
||||||
|
add_subdirectory(newgrf)
|
||||||
add_subdirectory(os)
|
add_subdirectory(os)
|
||||||
add_subdirectory(pathfinder)
|
add_subdirectory(pathfinder)
|
||||||
add_subdirectory(saveload)
|
add_subdirectory(saveload)
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "vehicle_base.h"
|
#include "vehicle_base.h"
|
||||||
#include "road.h"
|
#include "road.h"
|
||||||
#include "newgrf_roadstop.h"
|
#include "newgrf_roadstop.h"
|
||||||
|
#include "newgrf/newgrf_bytereader.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
#include "table/build_industry.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);
|
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);
|
typedef void (*SpecialSpriteHandler)(ByteReader &buf);
|
||||||
|
|
||||||
/** The maximum amount of stations a single GRF is allowed to add */
|
/** The maximum amount of stations a single GRF is allowed to add */
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
add_files(
|
||||||
|
newgrf_bytereader.cpp
|
||||||
|
newgrf_bytereader.h
|
||||||
|
)
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 */
|
Loading…
Reference in New Issue