1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-11-25 20:18:01 +00:00

Distinguish when to include the trailing NULL.

This commit is contained in:
Thomas Harte
2025-08-28 21:53:52 -04:00
parent 91831200d6
commit 095be3072b
20 changed files with 45 additions and 39 deletions

View File

@@ -13,7 +13,7 @@
using namespace Storage::Cartridge; using namespace Storage::Cartridge;
PRG::PRG(const std::string &file_name) { PRG::PRG(const std::string &file_name) {
Storage::FileHolder file(file_name.c_str(), FileHolder::FileMode::Read); Storage::FileHolder file(file_name.c_str(), FileMode::Read);
const auto loading_address = file.get_le<uint16_t>(); const auto loading_address = file.get_le<uint16_t>();
if(loading_address != 0xa000) { if(loading_address != 0xa000) {

View File

@@ -27,7 +27,7 @@ Disk2MG::DiskOrMassStorageDevice Disk2MG::open(const std::string &file_name) {
FileHolder file(file_name); FileHolder file(file_name);
// Check the signature. // Check the signature.
if(!file.check_signature("2IMG")) throw Error::InvalidFormat; if(!file.check_signature<SignatureType::String>("2IMG")) throw Error::InvalidFormat;
// Grab the creator, potential to fix the data size momentarily. // Grab the creator, potential to fix the data size momentarily.
const auto creator = file.read(4); const auto creator = file.read(4);

View File

@@ -23,10 +23,10 @@ CPCDSK::CPCDSK(const std::string &file_name) :
FileHolder file(file_name); FileHolder file(file_name);
is_read_only_ = file.is_known_read_only(); is_read_only_ = file.is_known_read_only();
if(!file.check_signature("MV - CPC")) { if(!file.check_signature<SignatureType::String>("MV - CPC")) {
is_extended_ = true; is_extended_ = true;
file.seek(0, Whence::SET); file.seek(0, Whence::SET);
if(!file.check_signature("EXTENDED")) if(!file.check_signature<SignatureType::String>("EXTENDED"))
throw Error::InvalidFormat; throw Error::InvalidFormat;
} }
@@ -276,7 +276,7 @@ void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::uni
} }
// Rewrite the entire disk image, in extended form. // Rewrite the entire disk image, in extended form.
Storage::FileHolder output(file_name_, Storage::FileHolder::FileMode::Rewrite); Storage::FileHolder output(file_name_, Storage::FileMode::Rewrite);
output.write(reinterpret_cast<const uint8_t *>("EXTENDED CPC DSK File\r\nDisk-Info\r\n"), 34); output.write(reinterpret_cast<const uint8_t *>("EXTENDED CPC DSK File\r\nDisk-Info\r\n"), 34);
output.write(reinterpret_cast<const uint8_t *>("Clock Signal "), 14); output.write(reinterpret_cast<const uint8_t *>("Clock Signal "), 14);
output.put(uint8_t(head_position_count_)); output.put(uint8_t(head_position_count_));

View File

@@ -19,7 +19,7 @@ using namespace Storage::Disk;
G64::G64(const std::string &file_name) : G64::G64(const std::string &file_name) :
file_(file_name) { file_(file_name) {
// read and check the file signature // read and check the file signature
if(!file_.check_signature("GCR-1541")) throw Error::InvalidFormat; if(!file_.check_signature<SignatureType::String>("GCR-1541")) throw Error::InvalidFormat;
// check the version number // check the version number
int version = file_.get(); int version = file_.get();

View File

@@ -15,7 +15,7 @@ using namespace Storage::Disk;
HFE::HFE(const std::string &file_name) : HFE::HFE(const std::string &file_name) :
file_(file_name) { file_(file_name) {
if(!file_.check_signature("HXCPICFE")) throw Error::InvalidFormat; if(!file_.check_signature<SignatureType::String>("HXCPICFE")) throw Error::InvalidFormat;
if(file_.get()) throw Error::UnknownVersion; if(file_.get()) throw Error::UnknownVersion;
track_count_ = file_.get(); track_count_ = file_.get();

View File

@@ -21,7 +21,7 @@ using namespace Storage::Disk;
IMD::IMD(const std::string &file_name) : file_(file_name) { IMD::IMD(const std::string &file_name) : file_(file_name) {
// Check for signature. // Check for signature.
if(!file_.check_signature("IMD")) { if(!file_.check_signature<SignatureType::String>("IMD")) {
throw Error::InvalidFormat; throw Error::InvalidFormat;
} }

View File

@@ -18,7 +18,7 @@ using namespace Storage::Disk;
OricMFMDSK::OricMFMDSK(const std::string &file_name) : OricMFMDSK::OricMFMDSK(const std::string &file_name) :
file_(file_name) { file_(file_name) {
if(!file_.check_signature("MFM_DISK")) if(!file_.check_signature<SignatureType::String>("MFM_DISK"))
throw Error::InvalidFormat; throw Error::InvalidFormat;
head_count_ = file_.get_le<uint32_t>(); head_count_ = file_.get_le<uint32_t>();

View File

@@ -391,7 +391,7 @@ private:
STX::STX(const std::string &file_name) : file_(file_name) { STX::STX(const std::string &file_name) : file_(file_name) {
// Require that this be a version 3 Pasti. // Require that this be a version 3 Pasti.
if(!file_.check_signature("RSY\0")) throw Error::InvalidFormat; if(!file_.check_signature<SignatureType::Binary>("RSY")) throw Error::InvalidFormat;
if(file_.get_le<uint16_t>() != 3) throw Error::InvalidFormat; if(file_.get_le<uint16_t>() != 3) throw Error::InvalidFormat;
// Skip: tool used, 2 reserved bytes. // Skip: tool used, 2 reserved bytes.

View File

@@ -33,9 +33,9 @@ WOZ::WOZ(const std::string &file_name) :
char(0xff), 0x0a, 0x0d, 0x0a char(0xff), 0x0a, 0x0d, 0x0a
}; };
const bool isWoz1 = file_.check_signature(signature1); const bool isWoz1 = file_.check_signature<SignatureType::Binary>(signature1);
file_.seek(0, Whence::SET); file_.seek(0, Whence::SET);
const bool isWoz2 = file_.check_signature(signature2); const bool isWoz2 = file_.check_signature<SignatureType::Binary>(signature2);
if(!isWoz1 && !isWoz2) throw Error::InvalidFormat; if(!isWoz1 && !isWoz2) throw Error::InvalidFormat;
type_ = isWoz2 ? Type::WOZ2 : Type::WOZ1; type_ = isWoz2 ? Type::WOZ2 : Type::WOZ1;

View File

@@ -25,18 +25,23 @@ enum class Whence: int {
END = SEEK_END, END = SEEK_END,
}; };
enum class SignatureType {
String,
Binary,
};
enum class FileMode {
ReadWrite,
Read,
Rewrite
};
class FileHolder final { class FileHolder final {
public: public:
enum class Error { enum class Error {
CantOpen = -1 CantOpen = -1
}; };
enum class FileMode {
ReadWrite,
Read,
Rewrite
};
~FileHolder(); ~FileHolder();
/*! /*!
@@ -70,7 +75,7 @@ public:
Optionally limits itself to only @c size bytes. Optionally limits itself to only @c size bytes.
*/ */
template <typename IntT, size_t size = sizeof(IntT)> template <typename IntT, size_t size = sizeof(IntT)>
void put_be(IntT value) { void put_be(const IntT value) {
auto shift = size * 8; auto shift = size * 8;
while(shift) { while(shift) {
shift -= 8; shift -= 8;
@@ -161,9 +166,10 @@ public:
@returns @c true if the bytes read match the signature; @c false otherwise. @returns @c true if the bytes read match the signature; @c false otherwise.
*/ */
template <size_t size> template <SignatureType type, size_t size>
bool check_signature(const char (&signature)[size]) { bool check_signature(const char (&signature)[size]) {
constexpr auto signature_length = size - 1; // Discard C-style trailing NULL if this is a string compare.
constexpr auto signature_length = size - (type == SignatureType::String ? 1 : 0);
std::array<uint8_t, size> stored_signature; std::array<uint8_t, size> stored_signature;
if(read(stored_signature) != size) { if(read(stored_signature) != size) {
@@ -215,7 +221,7 @@ private:
}; };
inline std::vector<uint8_t> contents_of(const std::string &file_name) { inline std::vector<uint8_t> contents_of(const std::string &file_name) {
FileHolder file(file_name, FileHolder::FileMode::Read); FileHolder file(file_name, FileMode::Read);
return file.read(size_t(file.stats().st_size)); return file.read(size_t(file.stats().st_size));
} }

View File

@@ -21,7 +21,7 @@ VHD::VHD(const std::string &file_name) : file_(file_name) {
default: throw std::exception(); default: throw std::exception();
} }
if(!file_.check_signature("conectix")) { if(!file_.check_signature<SignatureType::String>("conectix")) {
throw std::exception(); throw std::exception();
} }

View File

@@ -37,7 +37,7 @@ std::unique_ptr<Analyser::Static::Target> SZX::load(const std::string &file_name
result->state = std::unique_ptr<Reflection::Struct>(state); result->state = std::unique_ptr<Reflection::Struct>(state);
// Check signature and major version number. // Check signature and major version number.
if(!file.check_signature("ZXST")) { if(!file.check_signature<SignatureType::String>("ZXST")) {
return nullptr; return nullptr;
} }
const uint8_t major_version = file.get(); const uint8_t major_version = file.get();

View File

@@ -60,7 +60,7 @@ const auto ascii_signature = signature<0xea>;
} }
CAS::CAS(const std::string &file_name) { CAS::CAS(const std::string &file_name) {
Storage::FileHolder file(file_name, FileHolder::FileMode::Read); Storage::FileHolder file(file_name, FileMode::Read);
enum class Mode { enum class Mode {
Seeking, Seeking,

View File

@@ -15,11 +15,11 @@
using namespace Storage::Tape; using namespace Storage::Tape;
CSW::CSW(const std::string &file_name) { CSW::CSW(const std::string &file_name) {
Storage::FileHolder file(file_name, FileHolder::FileMode::Read); Storage::FileHolder file(file_name, FileMode::Read);
if(file.stats().st_size < 0x20) throw ErrorNotCSW; if(file.stats().st_size < 0x20) throw ErrorNotCSW;
// Check signature. // Check signature.
if(!file.check_signature("Compressed Square Wave")) { if(!file.check_signature<SignatureType::String>("Compressed Square Wave")) {
throw ErrorNotCSW; throw ErrorNotCSW;
} }

View File

@@ -15,9 +15,9 @@ using namespace Storage::Tape;
CommodoreTAP::CommodoreTAP(const std::string &file_name) : file_name_(file_name) { CommodoreTAP::CommodoreTAP(const std::string &file_name) : file_name_(file_name) {
Storage::FileHolder file(file_name); Storage::FileHolder file(file_name);
const bool is_c64 = file.check_signature("C64-TAPE-RAW"); const bool is_c64 = file.check_signature<SignatureType::String>("C64-TAPE-RAW");
file.seek(0, Whence::SET); file.seek(0, Whence::SET);
const bool is_c16 = file.check_signature("C16-TAPE-RAW"); const bool is_c16 = file.check_signature<SignatureType::String>("C16-TAPE-RAW");
if(!is_c64 && !is_c16) { if(!is_c64 && !is_c16) {
throw ErrorNotCommodoreTAP; throw ErrorNotCommodoreTAP;
} }
@@ -60,7 +60,7 @@ CommodoreTAP::Serialiser::Serialiser(
Pulse initial, Pulse initial,
bool half_waves, bool half_waves,
bool updated_layout) : bool updated_layout) :
file_(file_name, FileHolder::FileMode::Read), file_(file_name, FileMode::Read),
current_pulse_(initial), current_pulse_(initial),
half_waves_(half_waves), half_waves_(half_waves),
updated_layout_(updated_layout) updated_layout_(updated_layout)

View File

@@ -13,7 +13,7 @@
using namespace Storage::Tape; using namespace Storage::Tape;
OricTAP::OricTAP(const std::string &file_name) : file_name_(file_name) { OricTAP::OricTAP(const std::string &file_name) : file_name_(file_name) {
Storage::FileHolder file(file_name, FileHolder::FileMode::Read); Storage::FileHolder file(file_name, FileMode::Read);
// Check for a sequence of at least three 0x16s followed by a 0x24. // Check for a sequence of at least three 0x16s followed by a 0x24.
while(true) { while(true) {
@@ -34,7 +34,7 @@ std::unique_ptr<FormatSerialiser> OricTAP::format_serialiser() const {
return std::make_unique<Serialiser>(file_name_); return std::make_unique<Serialiser>(file_name_);
} }
OricTAP::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, FileHolder::FileMode::Read) { OricTAP::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, FileMode::Read) {
reset(); reset();
} }

View File

@@ -22,10 +22,10 @@ Log::Logger<Log::Source::TZX> logger;
} }
TZX::TZX(const std::string &file_name) : file_name_(file_name) { TZX::TZX(const std::string &file_name) : file_name_(file_name) {
Storage::FileHolder file(file_name, FileHolder::FileMode::Read); Storage::FileHolder file(file_name, FileMode::Read);
// Check for signature followed by a 0x1a // Check for signature followed by a 0x1a
if(!file.check_signature("ZXTape!")) throw ErrorNotTZX; if(!file.check_signature<SignatureType::String>("ZXTape!")) throw ErrorNotTZX;
if(file.get() != 0x1a) throw ErrorNotTZX; if(file.get() != 0x1a) throw ErrorNotTZX;
// Get version number // Get version number
@@ -40,7 +40,7 @@ std::unique_ptr<FormatSerialiser> TZX::format_serialiser() const {
return std::make_unique<Serialiser>(file_name_); return std::make_unique<Serialiser>(file_name_);
} }
TZX::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, FileHolder::FileMode::Read) { TZX::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, FileMode::Read) {
reset(); reset();
} }

View File

@@ -49,7 +49,7 @@
using namespace Storage::Tape; using namespace Storage::Tape;
PRG::PRG(const std::string &file_name) : file_name_(file_name) { PRG::PRG(const std::string &file_name) : file_name_(file_name) {
FileHolder file(file_name, FileHolder::FileMode::Read); FileHolder file(file_name, FileMode::Read);
// There's really no way to validate other than that if this file is larger than 64kb, // There's really no way to validate other than that if this file is larger than 64kb,
// of if load address + length > 65536 then it's broken. // of if load address + length > 65536 then it's broken.
@@ -68,7 +68,7 @@ std::unique_ptr<FormatSerialiser> PRG::format_serialiser() const {
} }
PRG::Serialiser::Serialiser(const std::string &file_name, uint16_t load_address, uint16_t length) : PRG::Serialiser::Serialiser(const std::string &file_name, uint16_t load_address, uint16_t length) :
file_(file_name, FileHolder::FileMode::Read), file_(file_name, FileMode::Read),
load_address_(load_address), load_address_(load_address),
length_(length), length_(length),
timings_(false) timings_(false)

View File

@@ -12,7 +12,7 @@
using namespace Storage::Tape; using namespace Storage::Tape;
ZX80O81P::ZX80O81P(const std::string &file_name) { ZX80O81P::ZX80O81P(const std::string &file_name) {
Storage::FileHolder file(file_name, FileHolder::FileMode::Read); Storage::FileHolder file(file_name, FileMode::Read);
// Grab file contents. // Grab file contents.
data_ = file.read(size_t(file.stats().st_size)); data_ = file.read(size_t(file.stats().st_size));

View File

@@ -40,7 +40,7 @@ std::unique_ptr<FormatSerialiser> ZXSpectrumTAP::format_serialiser() const {
return std::make_unique<Serialiser>(file_name_); return std::make_unique<Serialiser>(file_name_);
} }
ZXSpectrumTAP::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, FileHolder::FileMode::Read) { ZXSpectrumTAP::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, FileMode::Read) {
read_next_block(); read_next_block();
} }