diff --git a/Storage/Disk/DiskImage/DiskImage.hpp b/Storage/Disk/DiskImage/DiskImage.hpp index 8d2006b58..08b0aaa9e 100644 --- a/Storage/Disk/DiskImage/DiskImage.hpp +++ b/Storage/Disk/DiskImage/DiskImage.hpp @@ -50,12 +50,12 @@ public: @returns the @c Track at @c position underneath @c head if there are any detectable events there; returns @c nullptr otherwise. */ - virtual std::shared_ptr get_track_at_position(Track::Address address) = 0; + virtual std::unique_ptr track_at_position(Track::Address address) = 0; /*! Replaces the Tracks indicated by the map, that maps from physical address to track content. */ - virtual void set_tracks(const std::map> &) {} + virtual void set_tracks(const std::map> &) {} /*! Communicates that it is likely to be a while before any more tracks are written. @@ -72,6 +72,12 @@ public: This can avoid some degree of work when disk images offer sub-head-position precision. */ virtual bool tracks_differ(Track::Address lhs, Track::Address rhs) { return lhs != rhs; } + + /*! + Maps from an address to its canonical form; this provides a means for images that duplicate the same + track at different addresses to declare as much. + */ + virtual Track::Address canonical_address(Track::Address address) { return address; } }; class DiskImageHolderBase: public Disk { diff --git a/Storage/Disk/DiskImage/DiskImageImplementation.hpp b/Storage/Disk/DiskImage/DiskImageImplementation.hpp index 73a6034e0..198dca7bd 100644 --- a/Storage/Disk/DiskImage/DiskImageImplementation.hpp +++ b/Storage/Disk/DiskImage/DiskImageImplementation.hpp @@ -22,10 +22,10 @@ template void DiskImageHolder::flush_tracks() { if(!unwritten_tracks_.empty()) { if(!update_queue_) update_queue_ = std::make_unique>(); - using TrackMap = std::map>; - std::shared_ptr track_copies(new TrackMap); + using TrackMap = std::map>; + auto track_copies = std::make_shared(); for(const auto &address : unwritten_tracks_) { - track_copies->insert({address, std::shared_ptr(cached_tracks_[address]->clone())}); + track_copies->insert({address, std::unique_ptr(cached_tracks_[address]->clone())}); } unwritten_tracks_.clear(); @@ -46,12 +46,13 @@ template std::shared_ptr DiskImageHolder::get_track_at_po if(address.head >= get_head_count()) return nullptr; if(address.position >= get_maximum_head_position()) return nullptr; - auto cached_track = cached_tracks_.find(address); + const auto canonical_address = disk_image_.canonical_address(address); + auto cached_track = cached_tracks_.find(canonical_address); if(cached_track != cached_tracks_.end()) return cached_track->second; - std::shared_ptr track = disk_image_.get_track_at_position(address); + std::shared_ptr track = disk_image_.track_at_position(canonical_address); if(!track) return nullptr; - cached_tracks_[address] = track; + cached_tracks_[canonical_address] = track; return track; } diff --git a/Storage/Disk/DiskImage/Formats/AmigaADF.cpp b/Storage/Disk/DiskImage/Formats/AmigaADF.cpp index f20bccff3..be3a5c2c5 100644 --- a/Storage/Disk/DiskImage/Formats/AmigaADF.cpp +++ b/Storage/Disk/DiskImage/Formats/AmigaADF.cpp @@ -124,7 +124,7 @@ int AmigaADF::get_head_count() { return 2; } -std::shared_ptr AmigaADF::get_track_at_position(Track::Address address) { +std::unique_ptr AmigaADF::track_at_position(Track::Address address) { using namespace Storage::Encodings; // Create an MFM encoder. @@ -179,7 +179,7 @@ std::shared_ptr AmigaADF::get_track_at_position(Track::Address address) { encoder->add_byte(0xff); } - return std::make_shared(std::move(encoded_segment)); + return std::make_unique(std::move(encoded_segment)); } long AmigaADF::get_file_offset_for_position(Track::Address address) { diff --git a/Storage/Disk/DiskImage/Formats/AmigaADF.hpp b/Storage/Disk/DiskImage/Formats/AmigaADF.hpp index 2668eb9a5..20c882f62 100644 --- a/Storage/Disk/DiskImage/Formats/AmigaADF.hpp +++ b/Storage/Disk/DiskImage/Formats/AmigaADF.hpp @@ -31,7 +31,7 @@ public: // implemented to satisfy @c Disk HeadPosition get_maximum_head_position() final; int get_head_count() final; - std::shared_ptr get_track_at_position(Track::Address) final; + std::unique_ptr track_at_position(Track::Address) final; private: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/AppleDSK.cpp b/Storage/Disk/DiskImage/Formats/AppleDSK.cpp index 0d4a2fa5e..10cff1a66 100644 --- a/Storage/Disk/DiskImage/Formats/AppleDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/AppleDSK.cpp @@ -61,7 +61,7 @@ size_t AppleDSK::logical_sector_for_physical_sector(size_t physical) { return (physical * (is_prodos_ ? 8 : 7)) % 15; } -std::shared_ptr AppleDSK::get_track_at_position(Track::Address address) { +std::unique_ptr AppleDSK::track_at_position(Track::Address address) { std::vector track_data; { std::lock_guard lock_guard(file_.get_file_access_mutex()); @@ -93,10 +93,10 @@ std::shared_ptr AppleDSK::get_track_at_position(Track::Address address) { const size_t offset_in_fifths = size_t(address.position.as_int() % 5); segment.rotate_right(offset_in_fifths * segment.data.size() / 5); - return std::make_shared(segment); + return std::make_unique(segment); } -void AppleDSK::set_tracks(const std::map> &tracks) { +void AppleDSK::set_tracks(const std::map> &tracks) { std::map> tracks_by_address; for(const auto &pair: tracks) { // Decode the track. diff --git a/Storage/Disk/DiskImage/Formats/AppleDSK.hpp b/Storage/Disk/DiskImage/Formats/AppleDSK.hpp index 575643171..cccbc4bd7 100644 --- a/Storage/Disk/DiskImage/Formats/AppleDSK.hpp +++ b/Storage/Disk/DiskImage/Formats/AppleDSK.hpp @@ -31,8 +31,8 @@ public: // Implemented to satisfy @c DiskImage. HeadPosition get_maximum_head_position() final; - std::shared_ptr get_track_at_position(Track::Address) final; - void set_tracks(const std::map> &) final; + std::unique_ptr track_at_position(Track::Address) final; + void set_tracks(const std::map> &) final; bool get_is_read_only() final; private: diff --git a/Storage/Disk/DiskImage/Formats/CPCDSK.cpp b/Storage/Disk/DiskImage/Formats/CPCDSK.cpp index 28a0b9c41..82fd763cc 100644 --- a/Storage/Disk/DiskImage/Formats/CPCDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/CPCDSK.cpp @@ -198,7 +198,7 @@ std::size_t CPCDSK::index_for_track(::Storage::Disk::Track::Address address) { return size_t((address.position.as_int() * head_count_) + address.head); } -std::shared_ptr CPCDSK::get_track_at_position(::Storage::Disk::Track::Address address) { +std::unique_ptr CPCDSK::track_at_position(::Storage::Disk::Track::Address address) { // Given that thesea are interleaved images, determine which track, chronologically, is being requested. const std::size_t chronological_track = index_for_track(address); @@ -221,7 +221,7 @@ std::shared_ptr CPCDSK::get_track_at_position(::Storage::Disk::Track::Add track->filler_byte); } -void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::shared_ptr<::Storage::Disk::Track>> &tracks) { +void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::unique_ptr<::Storage::Disk::Track>> &tracks) { // Patch changed tracks into the disk image. for(auto &pair: tracks) { // Assume MFM for now; with extensions DSK can contain FM tracks. diff --git a/Storage/Disk/DiskImage/Formats/CPCDSK.hpp b/Storage/Disk/DiskImage/Formats/CPCDSK.hpp index 8a7386ee0..99e38f49a 100644 --- a/Storage/Disk/DiskImage/Formats/CPCDSK.hpp +++ b/Storage/Disk/DiskImage/Formats/CPCDSK.hpp @@ -34,8 +34,8 @@ public: HeadPosition get_maximum_head_position() final; int get_head_count() final; bool get_is_read_only() final; - void set_tracks(const std::map<::Storage::Disk::Track::Address, std::shared_ptr<::Storage::Disk::Track>> &tracks) final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; + void set_tracks(const std::map> &) final; + std::unique_ptr<::Storage::Disk::Track> track_at_position(::Storage::Disk::Track::Address) final; private: struct Track { diff --git a/Storage/Disk/DiskImage/Formats/D64.cpp b/Storage/Disk/DiskImage/Formats/D64.cpp index ea36fb46c..359a44836 100644 --- a/Storage/Disk/DiskImage/Formats/D64.cpp +++ b/Storage/Disk/DiskImage/Formats/D64.cpp @@ -38,7 +38,7 @@ HeadPosition D64::get_maximum_head_position() { return HeadPosition(number_of_tracks_); } -std::shared_ptr D64::get_track_at_position(const Track::Address address) { +std::unique_ptr D64::track_at_position(const Track::Address address) { // Figure out where this track starts on the disk. int offset_to_track = 0; int tracks_to_traverse = address.position.as_int(); @@ -135,5 +135,5 @@ std::shared_ptr D64::get_track_at_position(const Track::Address address) Encodings::CommodoreGCR::encode_block(§or_data[target_data_offset], end_of_data); } - return std::make_shared(PCMSegment(data)); + return std::make_unique(PCMSegment(data)); } diff --git a/Storage/Disk/DiskImage/Formats/D64.hpp b/Storage/Disk/DiskImage/Formats/D64.hpp index 8f7a537af..f5bc9d31c 100644 --- a/Storage/Disk/DiskImage/Formats/D64.hpp +++ b/Storage/Disk/DiskImage/Formats/D64.hpp @@ -27,7 +27,7 @@ public: D64(const std::string &file_name); HeadPosition get_maximum_head_position() final; - std::shared_ptr get_track_at_position(Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; private: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/DMK.cpp b/Storage/Disk/DiskImage/Formats/DMK.cpp index 66260258e..42613dc15 100644 --- a/Storage/Disk/DiskImage/Formats/DMK.cpp +++ b/Storage/Disk/DiskImage/Formats/DMK.cpp @@ -79,7 +79,7 @@ long DMK::get_file_offset_for_position(Track::Address address) { return (address.head*head_count_ + address.position.as_int()) * track_length_ + 16; } -std::shared_ptr<::Storage::Disk::Track> DMK::get_track_at_position(::Storage::Disk::Track::Address address) { +std::unique_ptr<::Storage::Disk::Track> DMK::track_at_position(::Storage::Disk::Track::Address address) { file_.seek(get_file_offset_for_position(address), SEEK_SET); // Read the IDAM table. @@ -179,5 +179,5 @@ std::shared_ptr<::Storage::Disk::Track> DMK::get_track_at_position(::Storage::Di idam_pointer++; } - return std::make_shared(segments); + return std::make_unique(segments); } diff --git a/Storage/Disk/DiskImage/Formats/DMK.hpp b/Storage/Disk/DiskImage/Formats/DMK.hpp index 9629750ea..5c33f691a 100644 --- a/Storage/Disk/DiskImage/Formats/DMK.hpp +++ b/Storage/Disk/DiskImage/Formats/DMK.hpp @@ -33,7 +33,7 @@ public: int get_head_count() final; bool get_is_read_only() final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; private: FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/G64.cpp b/Storage/Disk/DiskImage/Formats/G64.cpp index 2bdfc5d9e..e04d5a1bf 100644 --- a/Storage/Disk/DiskImage/Formats/G64.cpp +++ b/Storage/Disk/DiskImage/Formats/G64.cpp @@ -36,9 +36,7 @@ HeadPosition G64::get_maximum_head_position() { return HeadPosition(number_of_tracks_ > 84 ? number_of_tracks_ : 84, 2); } -std::shared_ptr G64::get_track_at_position(Track::Address address) { - std::shared_ptr resulting_track; - +std::unique_ptr G64::track_at_position(Track::Address address) { // seek to this track's entry in the track table file_.seek(long((address.position.as_half() * 4) + 0xc), SEEK_SET); @@ -93,7 +91,7 @@ std::shared_ptr G64::get_track_at_position(Track::Address address) { } } - resulting_track = std::make_shared(std::move(segments)); + return std::make_unique(std::move(segments)); } else { PCMSegment segment( Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(unsigned(speed_zone_offset)), @@ -101,11 +99,9 @@ std::shared_ptr G64::get_track_at_position(Track::Address address) { track_contents ); - resulting_track = std::make_shared(std::move(segment)); + return std::make_unique(std::move(segment)); } - // TODO: find out whether it's possible for a G64 to supply only a partial track. I don't think it is, which would make the - // above correct but supposing I'm wrong, the above would produce some incorrectly clocked tracks - - return resulting_track; + // TODO: find out whether it's possible for a G64 to supply only a partial track. I don't think it is, which + // would make the above correct but supposing I'm wrong, the above would produce some incorrectly clocked tracks. } diff --git a/Storage/Disk/DiskImage/Formats/G64.hpp b/Storage/Disk/DiskImage/Formats/G64.hpp index a50f50ba5..91715f8b7 100644 --- a/Storage/Disk/DiskImage/Formats/G64.hpp +++ b/Storage/Disk/DiskImage/Formats/G64.hpp @@ -31,7 +31,7 @@ public: // implemented to satisfy @c Disk HeadPosition get_maximum_head_position() final; - std::shared_ptr get_track_at_position(Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; using DiskImage::get_is_read_only; private: diff --git a/Storage/Disk/DiskImage/Formats/HFE.cpp b/Storage/Disk/DiskImage/Formats/HFE.cpp index 9354afefc..88ef9b00c 100644 --- a/Storage/Disk/DiskImage/Formats/HFE.cpp +++ b/Storage/Disk/DiskImage/Formats/HFE.cpp @@ -54,7 +54,7 @@ uint16_t HFE::seek_track(Track::Address address) { return track_length / 2; // Divide by two to give the track length for a single side. } -std::shared_ptr HFE::get_track_at_position(Track::Address address) { +std::unique_ptr HFE::track_at_position(Track::Address address) { PCMSegment segment; { std::lock_guard lock_guard(file_.get_file_access_mutex()); @@ -96,10 +96,10 @@ std::shared_ptr HFE::get_track_at_position(Track::Address address) { } } - return std::make_shared(segment); + return std::make_unique(segment); } -void HFE::set_tracks(const std::map> &tracks) { +void HFE::set_tracks(const std::map> &tracks) { for(auto &track : tracks) { std::unique_lock lock_guard(file_.get_file_access_mutex()); uint16_t track_length = seek_track(track.first); diff --git a/Storage/Disk/DiskImage/Formats/HFE.hpp b/Storage/Disk/DiskImage/Formats/HFE.hpp index f57890d8e..f0f0a52c5 100644 --- a/Storage/Disk/DiskImage/Formats/HFE.hpp +++ b/Storage/Disk/DiskImage/Formats/HFE.hpp @@ -33,8 +33,8 @@ public: HeadPosition get_maximum_head_position() final; int get_head_count() final; bool get_is_read_only() final; - void set_tracks(const std::map> &tracks) final; - std::shared_ptr get_track_at_position(Track::Address address) final; + void set_tracks(const std::map> &tracks) final; + std::unique_ptr track_at_position(Track::Address) final; private: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/IMD.cpp b/Storage/Disk/DiskImage/Formats/IMD.cpp index b94435a9a..2c91ba0ef 100644 --- a/Storage/Disk/DiskImage/Formats/IMD.cpp +++ b/Storage/Disk/DiskImage/Formats/IMD.cpp @@ -98,7 +98,7 @@ int IMD::get_head_count() { return heads_ + 1; } -std::shared_ptr<::Storage::Disk::Track> IMD::get_track_at_position(::Storage::Disk::Track::Address address) { +std::unique_ptr IMD::track_at_position(Track::Address address) { auto location = track_locations_.find(address); if(location == track_locations_.end()) { return nullptr; diff --git a/Storage/Disk/DiskImage/Formats/IMD.hpp b/Storage/Disk/DiskImage/Formats/IMD.hpp index d91668ef2..210f92eee 100644 --- a/Storage/Disk/DiskImage/Formats/IMD.hpp +++ b/Storage/Disk/DiskImage/Formats/IMD.hpp @@ -31,7 +31,7 @@ public: // DiskImage interface. HeadPosition get_maximum_head_position() final; int get_head_count() final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; private: FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/IPF.cpp b/Storage/Disk/DiskImage/Formats/IPF.cpp index c59405335..59f7da5fc 100644 --- a/Storage/Disk/DiskImage/Formats/IPF.cpp +++ b/Storage/Disk/DiskImage/Formats/IPF.cpp @@ -186,7 +186,7 @@ int IPF::get_head_count() { return head_count_; } -std::shared_ptr IPF::get_track_at_position([[maybe_unused]] Track::Address address) { +std::unique_ptr IPF::track_at_position([[maybe_unused]] Track::Address address) { // Get the track description, if it exists, and check either that the file has contents for the track. auto pair = tracks_.find(address); if(pair == tracks_.end()) { @@ -313,7 +313,7 @@ std::shared_ptr IPF::get_track_at_position([[maybe_unused]] Track::Addres ++block_count; } - return std::make_shared(segments); + return std::make_unique(segments); } /// @returns The correct bit length for @c block on a track of @c density. diff --git a/Storage/Disk/DiskImage/Formats/IPF.hpp b/Storage/Disk/DiskImage/Formats/IPF.hpp index d4a787502..384b5ca87 100644 --- a/Storage/Disk/DiskImage/Formats/IPF.hpp +++ b/Storage/Disk/DiskImage/Formats/IPF.hpp @@ -38,7 +38,7 @@ public: // implemented to satisfy @c Disk HeadPosition get_maximum_head_position() final; int get_head_count() final; - std::shared_ptr get_track_at_position(Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; private: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp b/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp index f0ce69d27..a6e536262 100644 --- a/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp +++ b/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp @@ -21,7 +21,7 @@ void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, uin first_sector_ = first_sector; } -std::shared_ptr MFMSectorDump::get_track_at_position(Track::Address address) { +std::unique_ptr MFMSectorDump::track_at_position(Track::Address address) { if(address.head >= get_head_count()) return nullptr; if(address.position.as_largest() >= get_maximum_head_position().as_largest()) return nullptr; @@ -44,7 +44,7 @@ std::shared_ptr MFMSectorDump::get_track_at_position(Track::Address addre density_); } -void MFMSectorDump::set_tracks(const std::map> &tracks) { +void MFMSectorDump::set_tracks(const std::map> &tracks) { uint8_t parsed_track[(128 << sector_size_)*sectors_per_track_]; // TODO: it would be more efficient from a file access and locking point of view to parse the sectors diff --git a/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp b/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp index 33d7a354a..bc81251f7 100644 --- a/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp +++ b/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp @@ -24,8 +24,8 @@ public: MFMSectorDump(const std::string &file_name); bool get_is_read_only() final; - void set_tracks(const std::map> &tracks) final; - std::shared_ptr get_track_at_position(Track::Address address) final; + void set_tracks(const std::map> &tracks) final; + std::unique_ptr track_at_position(Track::Address) final; protected: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/MSA.cpp b/Storage/Disk/DiskImage/Formats/MSA.cpp index a2917d471..595024d39 100644 --- a/Storage/Disk/DiskImage/Formats/MSA.cpp +++ b/Storage/Disk/DiskImage/Formats/MSA.cpp @@ -75,7 +75,7 @@ MSA::MSA(const std::string &file_name) : throw Error::InvalidFormat; } -std::shared_ptr<::Storage::Disk::Track> MSA::get_track_at_position(::Storage::Disk::Track::Address address) { +std::unique_ptr MSA::track_at_position(Track::Address address) { if(address.head >= sides_) return nullptr; const auto position = address.position.as_int(); diff --git a/Storage/Disk/DiskImage/Formats/MSA.hpp b/Storage/Disk/DiskImage/Formats/MSA.hpp index ac067efcf..78b4d4379 100644 --- a/Storage/Disk/DiskImage/Formats/MSA.hpp +++ b/Storage/Disk/DiskImage/Formats/MSA.hpp @@ -26,7 +26,7 @@ public: // Implemented to satisfy @c DiskImage. HeadPosition get_maximum_head_position() final; int get_head_count() final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; bool get_is_read_only() final { return false; } private: diff --git a/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp b/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp index 4f49ce338..c60fa3856 100644 --- a/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp +++ b/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp @@ -171,7 +171,7 @@ bool MacintoshIMG::get_is_read_only() { return file_.get_is_known_read_only(); } -std::shared_ptr<::Storage::Disk::Track> MacintoshIMG::get_track_at_position(::Storage::Disk::Track::Address address) { +std::unique_ptr MacintoshIMG::track_at_position(Track::Address address) { /* The format_ byte has the following meanings: @@ -246,13 +246,13 @@ std::shared_ptr<::Storage::Disk::Track> MacintoshIMG::get_track_at_position(::St // TODO: it seems some tracks are skewed respective to others; investigate further. // segment.rotate_right(3000); // Just a test, yo. - return std::make_shared(segment); + return std::make_unique(segment); } return nullptr; } -void MacintoshIMG::set_tracks(const std::map> &tracks) { +void MacintoshIMG::set_tracks(const std::map> &tracks) { std::map> tracks_by_address; for(const auto &pair: tracks) { // Determine a data rate for the track. diff --git a/Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp b/Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp index a24acadc0..e845942d2 100644 --- a/Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp +++ b/Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp @@ -47,8 +47,8 @@ public: int get_head_count() final; bool get_is_read_only() final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; - void set_tracks(const std::map> &tracks) final; + std::unique_ptr track_at_position(Track::Address) final; + void set_tracks(const std::map> &tracks) final; private: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/NIB.cpp b/Storage/Disk/DiskImage/Formats/NIB.cpp index 4e301bfba..d6edf1eba 100644 --- a/Storage/Disk/DiskImage/Formats/NIB.cpp +++ b/Storage/Disk/DiskImage/Formats/NIB.cpp @@ -54,7 +54,14 @@ long NIB::file_offset(Track::Address address) { return long(address.position.as_int()) * track_length; } -std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Disk::Track::Address address) { +Track::Address NIB::canonical_address(Track::Address address) { + return Track::Address( + address.head, + HeadPosition(address.position.as_int()) + ); +} + +std::unique_ptr NIB::track_at_position(Track::Address address) { static constexpr size_t MinimumSyncByteCount = 4; // NIBs contain data for a fixed quantity of integer-position tracks underneath a single head only. @@ -71,9 +78,6 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di std::vector track_data; { std::lock_guard lock_guard(file_.get_file_access_mutex()); - if(cached_offset_ == offset && cached_track_) { - return cached_track_; - } file_.seek(offset, SEEK_SET); track_data = file_.read(track_length); } @@ -133,12 +137,10 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di } std::lock_guard lock_guard(file_.get_file_access_mutex()); - cached_offset_ = offset; - cached_track_ = std::make_shared(segment); - return cached_track_; + return std::make_unique(segment); } -void NIB::set_tracks(const std::map> &tracks) { +void NIB::set_tracks(const std::map> &tracks) { std::map> tracks_by_address; // Convert to a map from address to a vector of data that contains the NIB representation @@ -186,5 +188,4 @@ void NIB::set_tracks(const std::map> &tra file_.seek(file_offset(track.first), SEEK_SET); file_.write(track.second); } - cached_track_ = nullptr; // Conservative, but safe. } diff --git a/Storage/Disk/DiskImage/Formats/NIB.hpp b/Storage/Disk/DiskImage/Formats/NIB.hpp index 500f3d353..4c3e34d90 100644 --- a/Storage/Disk/DiskImage/Formats/NIB.hpp +++ b/Storage/Disk/DiskImage/Formats/NIB.hpp @@ -27,20 +27,15 @@ public: // Implemented to satisfy @c DiskImage. HeadPosition get_maximum_head_position() final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; - void set_tracks(const std::map> &tracks) final; + Track::Address canonical_address(Track::Address) final; + std::unique_ptr track_at_position(Track::Address) final; + void set_tracks(const std::map> &tracks) final; bool get_is_read_only() final; private: FileHolder file_; long get_file_offset_for_position(Track::Address address); long file_offset(Track::Address address); - - // Cache for the last-generated track, given that head steps on an Apple II - // occur in quarter-track increments, so there'll routinely be four gets in - // a row for the same data. - long cached_offset_ = 0; - std::shared_ptr cached_track_; }; } diff --git a/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp b/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp index 9e4ec6060..50bb174b9 100644 --- a/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp @@ -50,7 +50,7 @@ long OricMFMDSK::get_file_offset_for_position(Track::Address address) { return long(seek_offset) * 6400 + 256; } -std::shared_ptr OricMFMDSK::get_track_at_position(Track::Address address) { +std::unique_ptr OricMFMDSK::track_at_position(Track::Address address) { PCMSegment segment; { std::lock_guard lock_guard(file_.get_file_access_mutex()); @@ -112,10 +112,10 @@ std::shared_ptr OricMFMDSK::get_track_at_position(Track::Address address) } } - return std::make_shared(segment); + return std::make_unique(segment); } -void OricMFMDSK::set_tracks(const std::map> &tracks) { +void OricMFMDSK::set_tracks(const std::map> &tracks) { for(const auto &track : tracks) { PCMSegment segment = Storage::Disk::track_serialisation(*track.second, Storage::Encodings::MFM::MFMBitLength); Storage::Encodings::MFM::Shifter shifter; diff --git a/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp b/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp index 0c38254d4..28c69bb62 100644 --- a/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp +++ b/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp @@ -32,8 +32,8 @@ public: int get_head_count() final; bool get_is_read_only() final; - void set_tracks(const std::map> &tracks) final; - std::shared_ptr get_track_at_position(Track::Address address) final; + void set_tracks(const std::map> &tracks) final; + std::unique_ptr track_at_position(Track::Address) final; private: Storage::FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/STX.cpp b/Storage/Disk/DiskImage/Formats/STX.cpp index c3884dffd..235552cee 100644 --- a/Storage/Disk/DiskImage/Formats/STX.cpp +++ b/Storage/Disk/DiskImage/Formats/STX.cpp @@ -182,7 +182,7 @@ public: (void)first_sync_; } - std::shared_ptr get_track() { + std::unique_ptr get_track() { // If no contents are supplied, return an unformatted track. if(sectors_.empty() && track_data_.empty()) { return nullptr; @@ -192,11 +192,11 @@ public: // changes and fuzzy bits in sectors only. if(sectors_.empty()) { PCMSegment segment; - std::unique_ptr encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data); + auto encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data); for(auto c: track_data_) { encoder->add_byte(c); } - return std::make_shared(segment); + return std::make_unique(segment); } // Otherwise, seek to encode the sectors, using the track data to @@ -377,7 +377,7 @@ public: track_size += 16; } - return std::make_shared(segments); + return std::make_unique(segments); } private: @@ -448,7 +448,7 @@ int STX::get_head_count() { return head_count_; } -std::shared_ptr<::Storage::Disk::Track> STX::get_track_at_position(::Storage::Disk::Track::Address address) { +std::unique_ptr STX::track_at_position(Track::Address address) { // These images have two sides, at most. if(address.head > 1) return nullptr; diff --git a/Storage/Disk/DiskImage/Formats/STX.hpp b/Storage/Disk/DiskImage/Formats/STX.hpp index d40d1bd8a..0b40eda3d 100644 --- a/Storage/Disk/DiskImage/Formats/STX.hpp +++ b/Storage/Disk/DiskImage/Formats/STX.hpp @@ -30,7 +30,7 @@ public: HeadPosition get_maximum_head_position() final; int get_head_count() final; - std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final; + std::unique_ptr track_at_position(Track::Address) final; private: FileHolder file_; diff --git a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp index b18242a5b..9398f4598 100644 --- a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp +++ b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp @@ -18,7 +18,7 @@ using namespace Storage::Disk; -std::shared_ptr Storage::Disk::track_for_sectors( +std::unique_ptr Storage::Disk::track_for_sectors( const uint8_t *const source, int number_of_sectors, uint8_t track, diff --git a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp index f681007da..246ed480d 100644 --- a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp +++ b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp @@ -17,7 +17,22 @@ namespace Storage::Disk { -std::shared_ptr track_for_sectors(const uint8_t *source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, Storage::Encodings::MFM::Density density); -void decode_sectors(const Track &track, uint8_t *destination, uint8_t first_sector, uint8_t last_sector, uint8_t sector_size, Storage::Encodings::MFM::Density density); +std::unique_ptr track_for_sectors( + const uint8_t *source, + int number_of_sectors, + uint8_t track, + uint8_t side, + uint8_t first_sector, + uint8_t size, + Storage::Encodings::MFM::Density density +); +void decode_sectors( + const Track &track, + uint8_t *destination, + uint8_t first_sector, + uint8_t last_sector, + uint8_t sector_size, + Storage::Encodings::MFM::Density density +); } diff --git a/Storage/Disk/DiskImage/Formats/WOZ.cpp b/Storage/Disk/DiskImage/Formats/WOZ.cpp index 37f237db3..c8f1970b4 100644 --- a/Storage/Disk/DiskImage/Formats/WOZ.cpp +++ b/Storage/Disk/DiskImage/Formats/WOZ.cpp @@ -147,7 +147,7 @@ bool WOZ::tracks_differ(Track::Address lhs, Track::Address rhs) { return offset1 != offset2; } -std::shared_ptr WOZ::get_track_at_position(Track::Address address) { +std::unique_ptr WOZ::track_at_position(Track::Address address) { const long offset = file_offset(address); if(offset == NoSuchTrack) { return nullptr; @@ -183,10 +183,10 @@ std::shared_ptr WOZ::get_track_at_position(Track::Address address) { } } - return std::make_shared(PCMSegment(number_of_bits, track_contents)); + return std::make_unique(PCMSegment(number_of_bits, track_contents)); } -void WOZ::set_tracks(const std::map> &tracks) { +void WOZ::set_tracks(const std::map> &tracks) { if(type_ == Type::WOZ2) return; for(const auto &pair: tracks) { diff --git a/Storage/Disk/DiskImage/Formats/WOZ.hpp b/Storage/Disk/DiskImage/Formats/WOZ.hpp index 9346ccb73..fa482c3b7 100644 --- a/Storage/Disk/DiskImage/Formats/WOZ.hpp +++ b/Storage/Disk/DiskImage/Formats/WOZ.hpp @@ -26,8 +26,8 @@ public: // Implemented to satisfy @c DiskImage. HeadPosition get_maximum_head_position() final; int get_head_count() final; - std::shared_ptr get_track_at_position(Track::Address address) final; - void set_tracks(const std::map> &tracks) final; + std::unique_ptr track_at_position(Track::Address) final; + void set_tracks(const std::map> &tracks) final; bool get_is_read_only() final; bool tracks_differ(Track::Address, Track::Address) final; diff --git a/Storage/Disk/Encodings/MFM/Encoder.cpp b/Storage/Disk/Encodings/MFM/Encoder.cpp index 25a9a38be..8166467b4 100644 --- a/Storage/Disk/Encodings/MFM/Encoder.cpp +++ b/Storage/Disk/Encodings/MFM/Encoder.cpp @@ -179,7 +179,7 @@ public: } }; -template std::shared_ptr +template std::unique_ptr GTrackWithSectors( const std::vector §ors, std::size_t post_index_address_mark_bytes, uint8_t post_index_address_mark_value, @@ -300,7 +300,7 @@ template std::shared_ptr // Allow the amount of data written to be up to 10% more than the expected size. Which is generous. if(segment.data.size() > max_size) segment.data.resize(max_size); - return std::make_shared(std::move(segment)); + return std::make_unique(std::move(segment)); } Encoder::Encoder(std::vector &target, std::vector *fuzzy_target) : @@ -339,7 +339,7 @@ void Encoder::add_crc(bool incorrectly) { namespace { template -std::shared_ptr TTrackWithSectors( +std::unique_ptr TTrackWithSectors( const std::vector §ors, std::optional sector_gap_length, std::optional sector_gap_filler_byte @@ -361,7 +361,7 @@ std::shared_ptr TTrackWithSectors( } -std::shared_ptr Storage::Encodings::MFM::TrackWithSectors( +std::unique_ptr Storage::Encodings::MFM::TrackWithSectors( Density density, const std::vector §ors, std::optional sector_gap_length, @@ -375,7 +375,7 @@ std::shared_ptr Storage::Encodings::MFM::TrackWithSectors( ); } -std::shared_ptr Storage::Encodings::MFM::TrackWithSectors( +std::unique_ptr Storage::Encodings::MFM::TrackWithSectors( Density density, const std::vector §ors, std::optional sector_gap_length, diff --git a/Storage/Disk/Encodings/MFM/Encoder.hpp b/Storage/Disk/Encodings/MFM/Encoder.hpp index 88ab4f38a..521cfe95e 100644 --- a/Storage/Disk/Encodings/MFM/Encoder.hpp +++ b/Storage/Disk/Encodings/MFM/Encoder.hpp @@ -27,13 +27,13 @@ namespace Storage::Encodings::MFM { @param sector_gap_length If specified, sets the distance in whole bytes between each ID and its data. @param sector_gap_filler_byte If specified, sets the value (unencoded) that is used to populate the gap between each ID and its data. */ -std::shared_ptr TrackWithSectors( +std::unique_ptr TrackWithSectors( Density density, const std::vector §ors, std::optional sector_gap_length = std::nullopt, std::optional sector_gap_filler_byte = std::nullopt); -std::shared_ptr TrackWithSectors( +std::unique_ptr TrackWithSectors( Density density, const std::vector §ors, std::optional sector_gap_length = std::nullopt,