1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-20 10:17:05 +00:00

Improve whence type safety.

This commit is contained in:
Thomas Harte
2025-08-28 17:41:58 -04:00
parent df589d9588
commit 8295d4511b
33 changed files with 149 additions and 143 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ Disk2MG::DiskOrMassStorageDevice Disk2MG::open(const std::string &file_name) {
const auto flags = file.get_le<uint32_t>();
// Skip the number of ProDOS blocks; this is surely implicit from the data size?
file.seek(4, SEEK_CUR);
file.seek(4, Whence::CUR);
// Get the offset and size of the disk image data.
const auto data_start = file.get_le<uint32_t>();
+1 -1
View File
@@ -52,7 +52,7 @@ AcornADF::AcornADF(const std::string &file_name) : MFMSectorDump(file_name) {
// So then .ADF files might be track-interleaved and might not be.
const auto has_identifier = [&](long location, bool permit_hugo, bool permit_nick) -> bool {
file_.seek(location, SEEK_SET);
file_.seek(location, Whence::SET);
uint8_t bytes[4];
file_.read(bytes, 4);
+1 -1
View File
@@ -133,7 +133,7 @@ std::unique_ptr<Track> AmigaADF::track_at_position(Track::Address address) const
auto encoder = MFM::GetMFMEncoder(encoded_segment.data);
// Grab the unencoded track.
file_.seek(get_file_offset_for_position(address), SEEK_SET);
file_.seek(get_file_offset_for_position(address), Whence::SET);
const std::vector<uint8_t> track_data = file_.read(512 * 11);
// Eleven sectors are then encoded.
+2 -2
View File
@@ -65,7 +65,7 @@ std::unique_ptr<Track> AppleDSK::track_at_position(Track::Address address) const
std::vector<uint8_t> track_data;
{
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(file_offset(address), SEEK_SET);
file_.seek(file_offset(address), Whence::SET);
track_data = file_.read(size_t(bytes_per_sector * sectors_per_track_));
}
@@ -117,7 +117,7 @@ void AppleDSK::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>>
// Grab the file lock and write out the new tracks.
std::lock_guard lock_guard(file_.file_access_mutex());
for(const auto &pair: tracks_by_address) {
file_.seek(file_offset(pair.first), SEEK_SET);
file_.seek(file_offset(pair.first), Whence::SET);
file_.write(pair.second);
}
}
+7 -7
View File
@@ -25,13 +25,13 @@ CPCDSK::CPCDSK(const std::string &file_name) :
if(!file.check_signature("MV - CPC")) {
is_extended_ = true;
file.seek(0, SEEK_SET);
file.seek(0, Whence::SET);
if(!file.check_signature("EXTENDED"))
throw Error::InvalidFormat;
}
// Don't really care about about the creator; skip.
file.seek(0x30, SEEK_SET);
file.seek(0x30, Whence::SET);
head_position_count_ = file.get();
head_count_ = file.get();
@@ -43,7 +43,7 @@ CPCDSK::CPCDSK(const std::string &file_name) :
if(is_extended_) {
// Skip two unused bytes and grab the track size table.
file.seek(2, SEEK_CUR);
file.seek(2, Whence::CUR);
for(int c = 0; c < head_position_count_ * head_count_; c++) {
track_sizes.push_back(size_t(file.get()) << 8);
}
@@ -55,7 +55,7 @@ CPCDSK::CPCDSK(const std::string &file_name) :
for(std::size_t c = 0; c < size_t(head_position_count_ * head_count_); c++) {
if(!is_extended_ || (track_sizes[c] > 0)) {
// Skip the introductory text, 'Track-Info\r\n' and its unused bytes.
file.seek(file_offset + 16, SEEK_SET);
file.seek(file_offset + 16, Whence::SET);
tracks_.emplace_back(new Track);
Track *track = tracks_.back().get();
@@ -81,7 +81,7 @@ CPCDSK::CPCDSK(const std::string &file_name) :
} else {
track->data_rate = Track::DataRate::Unknown;
track->data_encoding = Track::DataEncoding::Unknown;
file.seek(2, SEEK_CUR);
file.seek(2, Whence::CUR);
}
// Sector size, number of sectors, gap 3 length and the filler byte are then common
@@ -154,7 +154,7 @@ CPCDSK::CPCDSK(const std::string &file_name) :
// In a regular DSK, these two bytes are unused, and a special case is applied that ostensibly 8kb
// sectors are abbreviated to only 0x1800 bytes.
if(data_size == 0x2000) stored_data_size = 0x1800;
file.seek(2, SEEK_CUR);
file.seek(2, Whence::CUR);
}
// As per the weak/fuzzy sector extension, multiple samplings may be stored here.
@@ -167,7 +167,7 @@ CPCDSK::CPCDSK(const std::string &file_name) :
}
// Sector contents are at offset 0x100 into the track.
file.seek(file_offset + 0x100, SEEK_SET);
file.seek(file_offset + 0x100, Whence::SET);
for(auto &sector: track->sectors) {
for(auto &data : sector.samples) {
file.read(data.data(), data.size());
+1 -1
View File
@@ -54,7 +54,7 @@ std::unique_ptr<Track> D64::track_at_position(const Track::Address address) cons
}
// Seek to start of data.
file_.seek(offset_to_track * 256, SEEK_SET);
file_.seek(offset_to_track * 256, Whence::SET);
// Build up a PCM sampling of the GCR version of this track.
+2 -2
View File
@@ -56,7 +56,7 @@ DMK::DMK(const std::string &file_name) :
// Skip to the end of the header and check that this is
// "in the emulator's native format".
file_.seek(0xc, SEEK_SET);
file_.seek(0xc, Whence::SET);
const auto format = file_.get_le<uint32_t>();
if(format) throw Error::InvalidFormat;
}
@@ -80,7 +80,7 @@ long DMK::get_file_offset_for_position(const Track::Address address) const {
}
std::unique_ptr<::Storage::Disk::Track> DMK::track_at_position(const ::Storage::Disk::Track::Address address) const {
file_.seek(get_file_offset_for_position(address), SEEK_SET);
file_.seek(get_file_offset_for_position(address), Whence::SET);
// Read the IDAM table.
uint16_t idam_locations[64];
+3 -3
View File
@@ -21,11 +21,11 @@ FAT12::FAT12(const std::string &file_name) :
if(file_size < 512) throw Error::InvalidFormat;
// Inspect the FAT.
file_.seek(11, SEEK_SET);
file_.seek(11, Whence::SET);
sector_size_ = file_.get_le<uint16_t>();
file_.seek(19, SEEK_SET);
file_.seek(19, Whence::SET);
const auto total_sectors = file_.get_le<uint16_t>();
file_.seek(24, SEEK_SET);
file_.seek(24, Whence::SET);
sector_count_ = file_.get_le<uint16_t>();
head_count_ = file_.get_le<uint16_t>();
+4 -4
View File
@@ -38,7 +38,7 @@ HeadPosition G64::maximum_head_position() const {
std::unique_ptr<Track> G64::track_at_position(const Track::Address address) const {
// seek to this track's entry in the track table
file_.seek(long((address.position.as_half() * 4) + 0xc), SEEK_SET);
file_.seek(long((address.position.as_half() * 4) + 0xc), Whence::SET);
// read the track offset
const auto track_offset = file_.get_le<uint32_t>();
@@ -47,7 +47,7 @@ std::unique_ptr<Track> G64::track_at_position(const Track::Address address) cons
if(!track_offset) return nullptr;
// seek to the track start
file_.seek(long(track_offset), SEEK_SET);
file_.seek(long(track_offset), Whence::SET);
// get the real track length
const auto track_length = file_.get_le<uint16_t>();
@@ -56,7 +56,7 @@ std::unique_ptr<Track> G64::track_at_position(const Track::Address address) cons
const std::vector<uint8_t> track_contents = file_.read(track_length);
// seek to this track's entry in the speed zone table
file_.seek(long((address.position.as_half() * 4) + 0x15c), SEEK_SET);
file_.seek(long((address.position.as_half() * 4) + 0x15c), Whence::SET);
// read the speed zone offsrt
const auto speed_zone_offset = file_.get_le<uint32_t>();
@@ -64,7 +64,7 @@ std::unique_ptr<Track> G64::track_at_position(const Track::Address address) cons
// if the speed zone is not constant, create a track based on the whole table; otherwise create one that's constant
if(speed_zone_offset > 3) {
// seek to start of speed zone
file_.seek(long(speed_zone_offset), SEEK_SET);
file_.seek(long(speed_zone_offset), Whence::SET);
// read the speed zone bytes
const uint16_t speed_zone_length = (track_length + 3) >> 2;
+6 -6
View File
@@ -21,7 +21,7 @@ HFE::HFE(const std::string &file_name) :
track_count_ = file_.get();
head_count_ = file_.get();
file_.seek(7, SEEK_CUR);
file_.seek(7, Whence::CUR);
track_list_offset_ = long(file_.get_le<uint16_t>()) << 9;
}
@@ -43,13 +43,13 @@ int HFE::head_count() const {
uint16_t HFE::seek_track(const Track::Address address) const {
// Get track position and length from the lookup table; data is then always interleaved
// based on an assumption of two heads.
file_.seek(track_list_offset_ + address.position.as_int() * 4, SEEK_SET);
file_.seek(track_list_offset_ + address.position.as_int() * 4, Whence::SET);
long track_offset = long(file_.get_le<uint16_t>()) << 9; // Track offset, in units of 512 bytes.
const auto track_length = file_.get_le<uint16_t>(); // Track length, in bytes, containing both the front and back track.
file_.seek(track_offset, SEEK_SET);
if(address.head) file_.seek(256, SEEK_CUR);
file_.seek(track_offset, Whence::SET);
if(address.head) file_.seek(256, Whence::CUR);
return track_length / 2; // Divide by two to give the track length for a single side.
}
@@ -92,7 +92,7 @@ std::unique_ptr<Track> HFE::track_at_position(const Track::Address address) cons
// Advance the target pointer, and skip the next 256 bytes of the file
// (which will be for the other side of the disk).
c += length;
file_.seek(256, SEEK_CUR);
file_.seek(256, Whence::CUR);
}
}
@@ -119,7 +119,7 @@ void HFE::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tra
uint16_t length = uint16_t(std::min(256, data_length - c));
file_.write(&byte_segment[c], length);
c += length;
file_.seek(256, SEEK_CUR);
file_.seek(256, Whence::CUR);
}
lock_guard.unlock();
}
+7 -7
View File
@@ -33,7 +33,7 @@ IMD::IMD(const std::string &file_name) : file_(file_name) {
const auto location = file_.tell();
// Skip mode.
file_.seek(1, SEEK_CUR);
file_.seek(1, Whence::CUR);
// Grab relevant fields.
const uint8_t cylinder = file_.get();
@@ -53,16 +53,16 @@ IMD::IMD(const std::string &file_name) : file_(file_name) {
location);
// Skip sector numbers.
file_.seek(sector_count, SEEK_CUR);
file_.seek(sector_count, Whence::CUR);
// Skip cylinder map.
if(head & 0x80) {
file_.seek(sector_count, SEEK_CUR);
file_.seek(sector_count, Whence::CUR);
}
// Skip head map.
if(head & 0x40) {
file_.seek(sector_count, SEEK_CUR);
file_.seek(sector_count, Whence::CUR);
}
// Skip sectors.
@@ -73,12 +73,12 @@ IMD::IMD(const std::string &file_name) : file_(file_name) {
// Types with all sector data present.
case 0x01: case 0x03: case 0x05: case 0x07:
file_.seek(128 << sector_size, SEEK_CUR);
file_.seek(128 << sector_size, Whence::CUR);
break;
// Types with a single byte present.
case 0x02: case 0x04: case 0x06: case 0x08:
file_.seek(1, SEEK_CUR);
file_.seek(1, Whence::CUR);
break;
}
}
@@ -109,7 +109,7 @@ std::unique_ptr<Track> IMD::track_at_position(const Track::Address address) cons
}
// Seek to track, parse fully this time.
file_.seek(location->second, SEEK_SET);
file_.seek(location->second, Whence::SET);
const uint8_t mode = file_.get();
const uint8_t cylinder = file_.get();
+14 -14
View File
@@ -80,15 +80,15 @@ IPF::IPF(const std::string &file_name) : file_(file_name) {
is_sps_format_ = file_.get_be<uint32_t>() > 1;
// Skip: revision, file key and revision, CRC of the original .ctr, and minimum track.
file_.seek(20, SEEK_CUR);
file_.seek(20, Whence::CUR);
track_count_ = int(1 + file_.get_be<uint32_t>());
// Skip: min side.
file_.seek(4, SEEK_CUR);
file_.seek(4, Whence::CUR);
head_count_ = int(1 + file_.get_be<uint32_t>());
// Skip: creation date, time.
file_.seek(8, SEEK_CUR);
file_.seek(8, Whence::CUR);
platform_type_ = 0;
for(int c = 0; c < 4; c++) {
@@ -133,15 +133,15 @@ IPF::IPF(const std::string &file_name) : file_(file_name) {
description.density = TrackDescription::Density::Unknown;
}
file_.seek(12, SEEK_CUR); // Skipped: signal type, track bytes, start byte position.
file_.seek(12, Whence::CUR); // Skipped: signal type, track bytes, start byte position.
description.start_bit_pos = file_.get_be<uint32_t>();
description.data_bits = file_.get_be<uint32_t>();
description.gap_bits = file_.get_be<uint32_t>();
file_.seek(4, SEEK_CUR); // Skipped: track bits, which is entirely redundant.
file_.seek(4, Whence::CUR); // Skipped: track bits, which is entirely redundant.
description.block_count = file_.get_be<uint32_t>();
file_.seek(4, SEEK_CUR); // Skipped: encoder process.
file_.seek(4, Whence::CUR); // Skipped: encoder process.
description.has_fuzzy_bits = file_.get_be<uint32_t>() & 1;
// For some reason the authors decided to introduce another primary key,
@@ -154,7 +154,7 @@ IPF::IPF(const std::string &file_name) : file_(file_name) {
case block("DATA"): {
length += file_.get_be<uint32_t>();
file_.seek(8, SEEK_CUR); // Skipped: bit size, CRC.
file_.seek(8, Whence::CUR); // Skipped: bit size, CRC.
// Grab the data key and use that to establish the file starting
// position for this track.
@@ -174,7 +174,7 @@ IPF::IPF(const std::string &file_name) : file_(file_name) {
} break;
}
file_.seek(start_of_block + length, SEEK_SET);
file_.seek(start_of_block + length, Whence::SET);
}
}
@@ -198,7 +198,7 @@ std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) cons
}
// Seek to track content.
file_.seek(description.file_offset, SEEK_SET);
file_.seek(description.file_offset, Whence::SET);
// Read the block descriptions up front.
//
@@ -224,10 +224,10 @@ std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) cons
block.gap_bits = file_.get_be<uint32_t>();
if(is_sps_format_) {
block.gap_offset = file_.get_be<uint32_t>();
file_.seek(4, SEEK_CUR); // Skip 'cell type' which appears to provide no content.
file_.seek(4, Whence::CUR); // Skip 'cell type' which appears to provide no content.
} else {
// Skip potlower-resolution copies of data_bits and gap_bits.
file_.seek(8, SEEK_CUR);
file_.seek(8, Whence::CUR);
}
block.is_mfm = file_.get_be<uint32_t>() == 1;
@@ -246,7 +246,7 @@ std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) cons
const auto length_of_a_bit = bit_length(description.density, block_count);
if(block.gap_offset) {
file_.seek(description.file_offset + block.gap_offset, SEEK_SET);
file_.seek(description.file_offset + block.gap_offset, Whence::SET);
while(true) {
const uint8_t gap_header = file_.get();
if(!gap_header) break;
@@ -267,7 +267,7 @@ std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) cons
case Type::SampleLength:
printf("Adding sampled gap length %zu bits\n", length);
add_raw_data(segments, length_of_a_bit, length);
// file_.seek(long(length >> 3), SEEK_CUR);
// file_.seek(long(length >> 3), Whence::CUR);
break;
}
}
@@ -276,7 +276,7 @@ std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) cons
}
if(block.data_offset) {
file_.seek(description.file_offset + block.data_offset, SEEK_SET);
file_.seek(description.file_offset + block.data_offset, Whence::SET);
while(true) {
const uint8_t data_header = file_.get();
if(!data_header) break;
@@ -31,7 +31,7 @@ std::unique_ptr<Track> MFMSectorDump::track_at_position(Track::Address address)
{
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
sectors = file_.read(size);
}
@@ -64,7 +64,7 @@ void MFMSectorDump::set_tracks(const std::map<Track::Address, std::unique_ptr<Tr
std::lock_guard lock_guard(file_.file_access_mutex());
file_.ensure_is_at_least_length(file_offset);
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
file_.write(parsed_track);
}
file_.flush();
@@ -74,7 +74,7 @@ MacintoshIMG::MacintoshIMG(const std::string &file_name) :
}
// Get the length of the data and tag blocks.
file_.seek(64, SEEK_SET);
file_.seek(64, Whence::SET);
const auto data_block_length = file_.get_be<uint32_t>();
const auto tag_block_length = file_.get_be<uint32_t>();
const auto data_checksum = file_.get_be<uint32_t>();
@@ -141,7 +141,7 @@ void MacintoshIMG::construct_raw_gcr(const size_t offset, size_t size) {
}
raw_offset_ = long(offset);
file_.seek(raw_offset_, SEEK_SET);
file_.seek(raw_offset_, Whence::SET);
if(size == 819200) {
encoding_ = Encoding::GCR800;
format_ = 0x22;
@@ -320,18 +320,18 @@ void MacintoshIMG::set_tracks(const std::map<Track::Address, std::unique_ptr<Tra
if(!is_diskCopy_file_) {
// Just dump out the entire disk. Grossly lazy, possibly worth improving.
file_.seek(raw_offset_, SEEK_SET);
file_.seek(raw_offset_, Whence::SET);
file_.write(data_);
} else {
// Write out the sectors, and possibly the tags, and update checksums.
file_.seek(0x54, SEEK_SET);
file_.seek(0x54, Whence::SET);
file_.write(data_);
file_.write(tags_);
const auto data_checksum = checksum(data_);
const auto tag_checksum = checksum(tags_, 12);
file_.seek(0x48, SEEK_SET);
file_.seek(0x48, Whence::SET);
file_.put_be(data_checksum);
file_.put_be(tag_checksum);
}
+2 -2
View File
@@ -80,7 +80,7 @@ std::unique_ptr<Track> NIB::track_at_position(const Track::Address address) cons
std::vector<uint8_t> track_data;
{
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(offset, SEEK_SET);
file_.seek(offset, Whence::SET);
track_data = file_.read(track_length);
}
@@ -187,7 +187,7 @@ void NIB::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tra
// Lock the file and spool out.
std::lock_guard lock_guard(file_.file_access_mutex());
for(const auto &track: tracks_by_address) {
file_.seek(file_offset(track.first), SEEK_SET);
file_.seek(file_offset(track.first), Whence::SET);
file_.write(track.second);
}
}
@@ -54,7 +54,7 @@ std::unique_ptr<Track> OricMFMDSK::track_at_position(const Track::Address addres
PCMSegment segment;
{
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(get_file_offset_for_position(address), SEEK_SET);
file_.seek(get_file_offset_for_position(address), Whence::SET);
// The file format omits clock bits. So it's not a genuine MFM capture.
// A consumer must contextually guess when an FB, FC, etc is meant to be a control mark.
@@ -158,7 +158,7 @@ void OricMFMDSK::set_tracks(const std::map<Track::Address, std::unique_ptr<Track
long file_offset = get_file_offset_for_position(track.first);
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
std::size_t track_size = std::min(size_t(6400), parsed_track.size());
file_.write(parsed_track.data(), track_size);
}
+12 -12
View File
@@ -395,12 +395,12 @@ STX::STX(const std::string &file_name) : file_(file_name) {
if(file_.get_le<uint16_t>() != 3) throw Error::InvalidFormat;
// Skip: tool used, 2 reserved bytes.
file_.seek(4, SEEK_CUR);
file_.seek(4, Whence::CUR);
// Skip the track count, test for a new-style encoding, skip a reserved area.
file_.seek(1, SEEK_CUR);
file_.seek(1, Whence::CUR);
is_new_format_ = file_.get() == 2;
file_.seek(4, SEEK_CUR);
file_.seek(4, Whence::CUR);
// Set all tracks absent.
memset(offset_by_track_, 0, sizeof(offset_by_track_));
@@ -426,7 +426,7 @@ STX::STX(const std::string &file_name) : file_(file_name) {
if(file_.eof()) break;
// Skip fields other than track position, then fill in table position and advance.
file_.seek(10, SEEK_CUR);
file_.seek(10, Whence::CUR);
const uint8_t track_position = file_.get();
offset_by_track_[track_position] = offset;
@@ -436,7 +436,7 @@ STX::STX(const std::string &file_name) : file_(file_name) {
head_count_ = std::max(head_count_, ((track_position & 0x80) >> 6));
// Seek next track start.
file_.seek(offset + size, SEEK_SET);
file_.seek(offset + size, Whence::SET);
}
}
@@ -457,14 +457,14 @@ std::unique_ptr<Track> STX::track_at_position(const Track::Address address) cons
if(!offset_by_track_[track_index]) return nullptr;
// Seek to the track (skipping the record size field).
file_.seek(offset_by_track_[track_index] + 4, SEEK_SET);
file_.seek(offset_by_track_[track_index] + 4, Whence::SET);
// Grab the track description.
const auto fuzzy_size = file_.get_le<uint32_t>();
const auto sector_count = file_.get_le<uint16_t>();
const auto flags = file_.get_le<uint16_t>();
const size_t track_length = file_.get_le<uint16_t>();
file_.seek(2, SEEK_CUR); // Skip track type; despite being named, it's apparently unused.
file_.seek(2, Whence::CUR); // Skip track type; despite being named, it's apparently unused.
// If this is a trivial .ST-style sector dump, life is easy.
if(!(flags & 1)) {
@@ -485,7 +485,7 @@ std::unique_ptr<Track> STX::track_at_position(const Track::Address address) cons
sectors.back().data_duration = file_.get_le<uint16_t>();
file_.read(sectors.back().address);
sectors.back().status = file_.get();
file_.seek(1, SEEK_CUR);
file_.seek(1, Whence::CUR);
}
// If fuzzy masks are specified, attach them to their corresponding sectors.
@@ -508,7 +508,7 @@ std::unique_ptr<Track> STX::track_at_position(const Track::Address address) cons
// It should be true that the number of fuzzy masks caused
// exactly the correct number of fuzzy bytes to be read.
// But, just in case, check and possibly skip some.
file_.seek(long(fuzzy_size) - fuzzy_bytes_read, SEEK_CUR);
file_.seek(long(fuzzy_size) - fuzzy_bytes_read, Whence::CUR);
}
// There may or may not be a track image. Grab it if so.
@@ -534,15 +534,15 @@ std::unique_ptr<Track> STX::track_at_position(const Track::Address address) cons
// If the FDC record-not-found flag is set, there's no sector body to find.
// Otherwise there's a sector body in the file somewhere.
if(!(sector.status & 0x10)) {
file_.seek(sector.data_offset + sector_start, SEEK_SET);
file_.seek(sector.data_offset + sector_start, Whence::SET);
sector.contents = file_.read(sector.data_size());
end_of_data = std::max(end_of_data, file_.tell());
}
}
file_.seek(end_of_data, SEEK_SET);
file_.seek(end_of_data, Whence::SET);
// Grab timing info if available.
file_.seek(4, SEEK_CUR); // Skip the timing descriptor, as it includes no new information.
file_.seek(4, Whence::CUR); // Skip the timing descriptor, as it includes no new information.
for(auto &sector: sectors) {
// Skip any sector with no intra-sector bit width variation.
if(!(sector.status&1)) continue;
+8 -8
View File
@@ -34,7 +34,7 @@ WOZ::WOZ(const std::string &file_name) :
};
const bool isWoz1 = file_.check_signature(signature1, 8);
file_.seek(0, SEEK_SET);
file_.seek(0, Whence::SET);
const bool isWoz2 = file_.check_signature(signature2, 8);
if(!isWoz1 && !isWoz2) throw Error::InvalidFormat;
@@ -53,7 +53,7 @@ WOZ::WOZ(const std::string &file_name) :
}
// Retreat to the first byte after the CRC.
file_.seek(12, SEEK_SET);
file_.seek(12, Whence::SET);
// Parse all chunks up front.
bool has_tmap = false;
@@ -101,7 +101,7 @@ WOZ::WOZ(const std::string &file_name) :
break;
}
file_.seek(end_of_chunk, SEEK_SET);
file_.seek(end_of_chunk, Whence::SET);
}
if(tracks_offset_ == -1 || !has_tmap) throw Error::InvalidFormat;
@@ -158,7 +158,7 @@ std::unique_ptr<Track> WOZ::track_at_position(Track::Address address) const {
size_t number_of_bits;
{
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(offset, SEEK_SET);
file_.seek(offset, Whence::SET);
switch(type_) {
case Type::WOZ1:
@@ -166,7 +166,7 @@ std::unique_ptr<Track> WOZ::track_at_position(Track::Address address) const {
// number of bytes that actually had data in them, then a two-byte count of the number
// of bits that were used. Other information follows but is not intended for emulation.
track_contents = file_.read(6646);
file_.seek(2, SEEK_CUR);
file_.seek(2, Whence::CUR);
number_of_bits = std::min(file_.get_le<uint16_t>(), uint16_t(6646*8));
break;
@@ -174,10 +174,10 @@ std::unique_ptr<Track> WOZ::track_at_position(Track::Address address) const {
case Type::WOZ2: {
// In WOZ 2 an extra level of indirection allows for variable track sizes.
const auto starting_block = file_.get_le<uint16_t>();
file_.seek(2, SEEK_CUR); // Skip the block count; the amount of data to read is implied by the number of bits.
file_.seek(2, Whence::CUR); // Skip the block count; the amount of data to read is implied by the number of bits.
number_of_bits = file_.get_le<uint32_t>();
file_.seek(starting_block * 512, SEEK_SET);
file_.seek(starting_block * 512, Whence::SET);
track_contents = file_.read((number_of_bits + 7) >> 3);
} break;
}
@@ -213,7 +213,7 @@ void WOZ::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tra
// Grab the file lock, then write the CRC, then just dump the entire file buffer.
std::lock_guard lock_guard(file_.file_access_mutex());
file_.seek(8, SEEK_SET);
file_.seek(8, Whence::SET);
file_.put_le(crc);
file_.write(post_crc_contents_);
}
+2 -2
View File
@@ -72,8 +72,8 @@ std::size_t FileHolder::write(const uint8_t *buffer, const std::size_t size) {
return std::fwrite(buffer, 1, size, file_);
}
void FileHolder::seek(const long offset, const int whence) {
[[maybe_unused]] const auto result = std::fseek(file_, offset, whence);
void FileHolder::seek(const long offset, const Whence whence) {
[[maybe_unused]] const auto result = std::fseek(file_, offset, int(whence));
assert(!result);
}
+12 -6
View File
@@ -19,6 +19,12 @@
namespace Storage {
enum class Whence: int {
CUR = SEEK_CUR,
SET = SEEK_SET,
END = SEEK_END,
};
class FileHolder final {
public:
enum class Error {
@@ -104,13 +110,13 @@ public:
uint8_t get();
/*! Writes a single byte from @c file. */
void put(uint8_t value);
void put(uint8_t);
/*! Writes @c value a total of @c repeats times. */
void putn(std::size_t repeats, uint8_t value);
/*! Reads @c size bytes and returns them as a vector. */
std::vector<uint8_t> read(std::size_t size);
std::vector<uint8_t> read(std::size_t);
/*! Reads @c a.size() bytes into @c a.data(). */
template <size_t size> std::size_t read(std::array<uint8_t, size> &a) {
@@ -118,16 +124,16 @@ public:
}
/*! Reads @c size bytes and writes them to @c buffer. */
std::size_t read(uint8_t *buffer, std::size_t size);
std::size_t read(uint8_t *, std::size_t);
/*! Writes @c buffer one byte at a time in order. */
std::size_t write(const std::vector<uint8_t> &buffer);
std::size_t write(const std::vector<uint8_t> &);
/*! Writes @c buffer one byte at a time in order, writing @c size bytes in total. */
std::size_t write(const uint8_t *buffer, std::size_t size);
std::size_t write(const uint8_t *, std::size_t);
/*! Moves @c bytes from the anchor indicated by @c whence: SEEK_SET, SEEK_CUR or SEEK_END. */
void seek(long offset, int whence);
void seek(long offset, Whence);
/*! @returns The current cursor position within this file. */
long tell() const;
+2 -2
View File
@@ -36,7 +36,7 @@ std::vector<uint8_t> HDV::get_block(size_t address) {
const auto file_offset = offset_for_block(source_address);
if(source_address >= 0) {
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
return mapper_.convert_source_block(source_address, file_.read(get_block_size()));
} else {
return mapper_.convert_source_block(source_address);
@@ -48,7 +48,7 @@ void HDV::set_block(size_t address, const std::vector<uint8_t> &data) {
const auto file_offset = offset_for_block(source_address);
if(source_address >= 0 && file_offset >= 0) {
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
file_.write(data);
}
}
+2 -2
View File
@@ -36,7 +36,7 @@ std::vector<uint8_t> HFV::get_block(size_t address) {
const auto source_address = mapper_.to_source_address(address);
if(source_address >= 0 && size_t(source_address)*get_block_size() < size_t(file_.stats().st_size)) {
const long file_offset = long(get_block_size()) * long(source_address);
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
return mapper_.convert_source_block(source_address, file_.read(get_block_size()));
} else {
return mapper_.convert_source_block(source_address);
@@ -47,7 +47,7 @@ void HFV::set_block(size_t address, const std::vector<uint8_t> &contents) {
const auto source_address = mapper_.to_source_address(address);
if(source_address >= 0 && size_t(source_address)*get_block_size() < size_t(file_.stats().st_size)) {
const long file_offset = long(get_block_size()) * long(source_address);
file_.seek(file_offset, SEEK_SET);
file_.seek(file_offset, Whence::SET);
file_.write(contents);
} else {
writes_[address] = contents;
@@ -36,13 +36,13 @@ public:
}
std::vector<uint8_t> get_block(size_t address) final {
file_.seek(file_start_ + long(address * sector_size), SEEK_SET);
file_.seek(file_start_ + long(address * sector_size), Whence::SET);
return file_.read(sector_size);
}
void set_block(size_t address, const std::vector<uint8_t> &contents) final {
assert(contents.size() == sector_size);
file_.seek(file_start_ + long(address * sector_size), SEEK_SET);
file_.seek(file_start_ + long(address * sector_size), Whence::SET);
file_.write(contents);
}
+6 -6
View File
@@ -13,11 +13,11 @@ using namespace Storage::MassStorage;
VHD::VHD(const std::string &file_name) : file_(file_name) {
// Find footer; this may be the final 511 or final 512 bytes of the file.
// Find what might be the start of the 'conectix' [sic] signature.
file_.seek(-511, SEEK_END);
file_.seek(-511, Whence::END);
const auto c = file_.get();
switch(c) {
case 'c': file_.seek(-511, SEEK_END); break;
case 'o': file_.seek(-512, SEEK_END); break;
case 'c': file_.seek(-511, Whence::END); break;
case 'o': file_.seek(-512, Whence::END); break;
default: throw std::exception();
}
@@ -25,16 +25,16 @@ VHD::VHD(const std::string &file_name) : file_(file_name) {
throw std::exception();
}
file_.seek(4, SEEK_CUR); // Skip 'Features', which would at best classify this disk as temporary or not.
file_.seek(4, Whence::CUR); // Skip 'Features', which would at best classify this disk as temporary or not.
const auto major_version = file_.get_be<uint16_t>();
if(major_version > 1) {
throw std::exception();
}
file_.seek(2, SEEK_CUR); // Skip minor version number.
file_.seek(2, Whence::CUR); // Skip minor version number.
data_offset_ = file_.get_be<uint64_t>();
file_.seek(32, SEEK_CUR); // Skip creator and timestamp fields, original size and current size.
file_.seek(32, Whence::CUR); // Skip creator and timestamp fields, original size and current size.
// const auto current_size = file_.get_be<uint64_t>();
cylinders_ = file_.get_be<uint16_t>();
+1 -1
View File
@@ -191,7 +191,7 @@ std::unique_ptr<Analyser::Static::Target> SZX::load(const std::string &file_name
}
// Advance to the next block.
file.seek(location + size, SEEK_SET);
file.seek(location + size, Whence::SET);
}
return result;
+5 -5
View File
@@ -130,7 +130,7 @@ std::unique_ptr<Analyser::Static::Target> Z80::load(const std::string &file_name
state->last_7ffd = file.get();
file.seek(1, SEEK_CUR);
file.seek(1, Whence::CUR);
if(file.get() & 0x80) {
// The 'hardware modify' bit, which inexplicably does this:
switch(result->model) {
@@ -160,13 +160,13 @@ std::unique_ptr<Analyser::Static::Target> Z80::load(const std::string &file_name
}
// Skip: Spectator flag, MGT, Multiface and other ROM flags.
file.seek(5, SEEK_CUR);
file.seek(5, Whence::CUR);
// Skip: highly Z80-the-emulator-specific stuff about user-defined joystick.
file.seek(20, SEEK_CUR);
file.seek(20, Whence::CUR);
// Skip: Disciple/Plus D stuff.
file.seek(3, SEEK_CUR);
file.seek(3, Whence::CUR);
if(bonus_header_size == 55) {
state->last_1ffd = file.get();
@@ -202,7 +202,7 @@ std::unique_ptr<Analyser::Static::Target> Z80::load(const std::string &file_name
}
assert(location + block_size == file.tell());
file.seek(location + block_size, SEEK_SET);
file.seek(location + block_size, Whence::SET);
}
return result;
+11 -11
View File
@@ -80,7 +80,7 @@ CAS::CAS(const std::string &file_name) {
// Check for other 1fs in this stream, and repeat from there if any.
for(size_t c = 1; c < 8; ++c) {
if(signature[c] == 0x1f) {
file.seek(header_position + long(c), SEEK_SET);
file.seek(header_position + long(c), Whence::SET);
break;
} else {
// Attach any unexpected bytes to the back of the most recent chunk.
@@ -105,7 +105,7 @@ CAS::CAS(const std::string &file_name) {
switch(parsing_mode) {
case Mode::Seeking: {
if(is_ascii || is_binary || is_basic) {
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
chunks_.emplace_back(!chunks_.empty(), true, file.read(10 + 6));
if(is_ascii) parsing_mode = Mode::ASCII;
@@ -113,10 +113,10 @@ CAS::CAS(const std::string &file_name) {
if(is_basic) parsing_mode = Mode::BASIC;
} else {
// Raw data appears now. Grab its length and keep going.
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
const auto length = file.get_le<uint16_t>();
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
chunks_.emplace_back(false, false, file.read(size_t(length) + 2));
}
} break;
@@ -124,10 +124,10 @@ CAS::CAS(const std::string &file_name) {
case Mode::ASCII:
// Keep reading ASCII in 256-byte segments until a non-ASCII chunk arrives.
if(is_binary || is_basic || is_ascii) {
file.seek(header_position, SEEK_SET);
file.seek(header_position, Whence::SET);
parsing_mode = Mode::Seeking;
} else {
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
chunks_.emplace_back(false, false, file.read(256));
}
break;
@@ -135,11 +135,11 @@ CAS::CAS(const std::string &file_name) {
case Mode::Binary: {
// Get the start and end addresses in order to figure out how much data
// is here.
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
const auto start_address = file.get_le<uint16_t>();
const auto end_address = file.get_le<uint16_t>();
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
const auto length = end_address - start_address + 1;
chunks_.emplace_back(false, false, file.read(size_t(length) + 6));
@@ -149,18 +149,18 @@ CAS::CAS(const std::string &file_name) {
case Mode::BASIC: {
// Horror of horrors, this will mean actually following the BASIC
// linked list of line contents.
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
uint16_t address = 0x8001; // the BASIC start address.
while(true) {
const auto next_line_address = file.get_le<uint16_t>();
if(!next_line_address || file.eof()) break;
file.seek(next_line_address - address - 2, SEEK_CUR);
file.seek(next_line_address - address - 2, Whence::CUR);
address = next_line_address;
}
const auto length = (file.tell() - 1) - (header_position + 8);
// Create the chunk and return to regular parsing.
file.seek(header_position + 8, SEEK_SET);
file.seek(header_position + 8, Whence::SET);
chunks_.emplace_back(false, false, file.read(size_t(length)));
parsing_mode = Mode::Seeking;
} break;
+3 -3
View File
@@ -43,10 +43,10 @@ CSW::CSW(const std::string &file_name) {
pulse_.type = (file.get() & 1) ? Pulse::High : Pulse::Low;
file.seek(0x20, SEEK_SET);
file.seek(0x20, Whence::SET);
} else {
pulse_.length.clock_rate = file.get_le<uint32_t>();
file.seek(4, SEEK_CUR); // Skip number of waves.
file.seek(4, Whence::CUR); // Skip number of waves.
switch(file.get()) {
case 1: compression_type = CompressionType::RLE; break;
case 2: compression_type = CompressionType::ZRLE; break;
@@ -57,7 +57,7 @@ CSW::CSW(const std::string &file_name) {
const uint8_t extension_length = file.get();
if(file.stats().st_size < 0x34 + extension_length) throw ErrorNotCSW;
file.seek(0x34 + extension_length, SEEK_SET);
file.seek(0x34 + extension_length, Whence::SET);
}
// Grab all data remaining in the file.
+3 -3
View File
@@ -16,7 +16,7 @@ CommodoreTAP::CommodoreTAP(const std::string &file_name) : file_name_(file_name)
Storage::FileHolder file(file_name);
const bool is_c64 = file.check_signature("C64-TAPE-RAW");
file.seek(0, SEEK_SET);
file.seek(0, Whence::SET);
const bool is_c16 = file.check_signature("C16-TAPE-RAW");
if(!is_c64 && !is_c16) {
throw ErrorNotCommodoreTAP;
@@ -34,7 +34,7 @@ CommodoreTAP::CommodoreTAP(const std::string &file_name) : file_name_(file_name)
// Read clock rate-implying bytes.
platform_ = Platform(file.get());
const VideoStandard video = VideoStandard(file.get());
file.seek(1, SEEK_CUR);
file.seek(1, Whence::CUR);
const bool double_clock = platform_ != Platform::C16 || !half_waves_; // TODO: is the platform check correct?
@@ -69,7 +69,7 @@ CommodoreTAP::Serialiser::Serialiser(
}
void CommodoreTAP::Serialiser::reset() {
file_.seek(0x14, SEEK_SET);
file_.seek(0x14, Whence::SET);
current_pulse_.type = Pulse::High; // Implies that the first posted wave will be ::Low.
is_at_end_ = false;
}
+1 -1
View File
@@ -39,7 +39,7 @@ OricTAP::Serialiser::Serialiser(const std::string &file_name) : file_(file_name,
}
void OricTAP::Serialiser::reset() {
file_.seek(0, SEEK_SET);
file_.seek(0, Whence::SET);
bit_count_ = 13;
phase_ = next_phase_ = LeadIn;
phase_counter_ = 0;
+15 -15
View File
@@ -47,7 +47,7 @@ TZX::Serialiser::Serialiser(const std::string &file_name) : file_(file_name, Fil
void TZX::Serialiser::reset() {
clear();
set_is_at_end(false);
file_.seek(0x0a, SEEK_SET);
file_.seek(0x0a, Whence::SET);
// This is a workaround for arguably dodgy ZX80/ZX81 TZXs; they launch straight
// into data but both machines require a gap before data begins. So impose
@@ -151,7 +151,7 @@ void TZX::Serialiser::get_generalised_data_block() {
post_gap(pause_after_block);
// This should be unnecessary, but intends to preserve sanity.
file_.seek(endpoint, SEEK_SET);
file_.seek(endpoint, Whence::SET);
}
void TZX::Serialiser::get_generalised_segment(
@@ -233,7 +233,7 @@ void TZX::Serialiser::get_standard_speed_data_block() {
const uint8_t first_byte = file_.get();
data_block.length_of_pilot_tone = (first_byte < 128) ? 8063 : 3223;
file_.seek(-1, SEEK_CUR);
file_.seek(-1, Whence::CUR);
get_data_block(data_block);
}
@@ -348,7 +348,7 @@ void TZX::Serialiser::get_pause() {
}
void TZX::Serialiser::get_set_signal_level() {
file_.seek(4, SEEK_CUR);
file_.seek(4, Whence::CUR);
const uint8_t level = file_.get();
current_level_ = !!level;
}
@@ -438,7 +438,7 @@ void TZX::Serialiser::post_pulse(const Storage::Time &time) {
void TZX::Serialiser::ignore_group_start() {
const uint8_t length = file_.get();
file_.seek(length, SEEK_CUR);
file_.seek(length, Whence::CUR);
}
void TZX::Serialiser::ignore_group_end() {
@@ -459,7 +459,7 @@ void TZX::Serialiser::ignore_loop_end() {
void TZX::Serialiser::ignore_call_sequence() {
const auto number_of_entries = file_.get_le<uint16_t>();
file_.seek(number_of_entries * sizeof(uint16_t), SEEK_CUR);
file_.seek(number_of_entries * sizeof(uint16_t), Whence::CUR);
}
void TZX::Serialiser::ignore_return_from_sequence() {
@@ -467,44 +467,44 @@ void TZX::Serialiser::ignore_return_from_sequence() {
void TZX::Serialiser::ignore_select_block() {
const auto length_of_block = file_.get_le<uint16_t>();
file_.seek(length_of_block, SEEK_CUR);
file_.seek(length_of_block, Whence::CUR);
}
void TZX::Serialiser::ignore_stop_tape_if_in_48kb_mode() {
file_.seek(4, SEEK_CUR);
file_.seek(4, Whence::CUR);
}
void TZX::Serialiser::ignore_custom_info_block() {
file_.seek(0x10, SEEK_CUR);
file_.seek(0x10, Whence::CUR);
const auto length = file_.get_le<uint32_t>();
file_.seek(length, SEEK_CUR);
file_.seek(length, Whence::CUR);
}
// MARK: - Messaging
void TZX::Serialiser::ignore_text_description() {
const uint8_t length = file_.get();
file_.seek(length, SEEK_CUR);
file_.seek(length, Whence::CUR);
}
void TZX::Serialiser::ignore_message_block() {
const uint8_t time_for_display = file_.get();
const uint8_t length = file_.get();
file_.seek(length, SEEK_CUR);
file_.seek(length, Whence::CUR);
(void)time_for_display;
}
void TZX::Serialiser::ignore_archive_info() {
const auto length = file_.get_le<uint16_t>();
file_.seek(length, SEEK_CUR);
file_.seek(length, Whence::CUR);
}
void TZX::Serialiser::get_hardware_type() {
// TODO: pick a way to retain and communicate this.
const uint8_t number_of_machines = file_.get();
file_.seek(number_of_machines * 3, SEEK_CUR);
file_.seek(number_of_machines * 3, Whence::CUR);
}
void TZX::Serialiser::ignore_glue_block() {
file_.seek(9, SEEK_CUR);
file_.seek(9, Whence::CUR);
}
+2 -2
View File
@@ -100,7 +100,7 @@ Storage::Tape::Pulse PRG::Serialiser::next_pulse() {
void PRG::Serialiser::reset() {
bit_phase_ = 3;
file_.seek(2, SEEK_SET);
file_.seek(2, Whence::SET);
file_phase_ = FilePhaseLeadIn;
phase_offset_ = 0;
copy_mask_ = 0x80;
@@ -157,7 +157,7 @@ void PRG::Serialiser::get_next_output_token() {
break;
case FilePhaseData:
copy_mask_ ^= 0x80;
file_.seek(2, SEEK_SET);
file_.seek(2, Whence::SET);
if(copy_mask_) {
file_phase_ = FilePhaseAtEnd;
}
+2 -2
View File
@@ -32,7 +32,7 @@ ZXSpectrumTAP::ZXSpectrumTAP(const std::string &file_name) : file_name_(file_nam
throw ErrorNotZXSpectrumTAP;
}
file.seek(block_length, SEEK_CUR);
file.seek(block_length, Whence::CUR);
}
}
@@ -49,7 +49,7 @@ bool ZXSpectrumTAP::Serialiser::is_at_end() const {
}
void ZXSpectrumTAP::Serialiser::reset() {
file_.seek(0, SEEK_SET);
file_.seek(0, Whence::SET);
read_next_block();
}