mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 16:31:31 +00:00
Merge pull request #208 from TomHarte/SpecialCharacters
Improves the CPC static analyser's correct file name predictions
This commit is contained in:
commit
9b21ef1507
@ -28,19 +28,25 @@ static bool is_implied_extension(const std::string &extension) {
|
||||
strcmp_insensitive(extension.c_str(), "BIN");
|
||||
}
|
||||
|
||||
static void right_trim(std::string &string) {
|
||||
string.erase(std::find_if(string.rbegin(), string.rend(), [](int ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), string.end());
|
||||
}
|
||||
|
||||
static std::string RunCommandFor(const Storage::Disk::CPM::File &file) {
|
||||
// Trim spaces from the name.
|
||||
std::string name = file.name;
|
||||
name.erase(std::find_if(name.rbegin(), name.rend(), [](int ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), name.end());
|
||||
right_trim(name);
|
||||
|
||||
// Form the basic command.
|
||||
std::string command = "run\"" + name;
|
||||
|
||||
// Consider whether the extension is required.
|
||||
if(!is_implied_extension(file.type)) {
|
||||
command += "." + file.type;
|
||||
std::string type = file.type;
|
||||
right_trim(type);
|
||||
command += "." + type;
|
||||
}
|
||||
|
||||
// Add a newline and return.
|
||||
@ -50,14 +56,35 @@ static std::string RunCommandFor(const Storage::Disk::CPM::File &file) {
|
||||
static void InspectDataCatalogue(
|
||||
const Storage::Disk::CPM::Catalogue &catalogue,
|
||||
StaticAnalyser::Target &target) {
|
||||
// Make a copy of all files and filter out any that are marked as system.
|
||||
std::vector<Storage::Disk::CPM::File> candidate_files = catalogue.files;
|
||||
|
||||
// Remove all files with untypable characters.
|
||||
candidate_files.erase(
|
||||
std::remove_if(candidate_files.begin(), candidate_files.end(), [](const Storage::Disk::CPM::File &file) {
|
||||
return file.system;
|
||||
for(auto c : file.name) {
|
||||
if(c < 32) return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
candidate_files.end());
|
||||
|
||||
// If that leaves a mix of 'system' (i.e. hidden) and non-system files, remove the system files.
|
||||
bool are_all_system = true;
|
||||
for(auto &file : candidate_files) {
|
||||
if(!file.system) {
|
||||
are_all_system = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!are_all_system) {
|
||||
candidate_files.erase(
|
||||
std::remove_if(candidate_files.begin(), candidate_files.end(), [](const Storage::Disk::CPM::File &file) {
|
||||
return file.system;
|
||||
}),
|
||||
candidate_files.end());
|
||||
}
|
||||
|
||||
// If there's just one file, run that.
|
||||
if(candidate_files.size() == 1) {
|
||||
target.loadingCommand = RunCommandFor(candidate_files[0]);
|
||||
@ -95,6 +122,25 @@ static void InspectDataCatalogue(
|
||||
return;
|
||||
}
|
||||
|
||||
// One more guess: if only one remaining candidate file has a different name than the others,
|
||||
// assume it is intended to stand out.
|
||||
std::map<std::string, int> name_counts;
|
||||
std::map<std::string, size_t> indices_by_name;
|
||||
size_t index = 0;
|
||||
for(auto &file : candidate_files) {
|
||||
name_counts[file.name]++;
|
||||
indices_by_name[file.name] = index;
|
||||
index++;
|
||||
}
|
||||
if(name_counts.size() == 2) {
|
||||
for(auto &pair : name_counts) {
|
||||
if(pair.second == 1) {
|
||||
target.loadingCommand = RunCommandFor(candidate_files[indices_by_name[pair.first]]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Desperation.
|
||||
target.loadingCommand = "cat\n";
|
||||
}
|
||||
|
@ -24,22 +24,26 @@ std::unique_ptr<Storage::Disk::CPM::Catalogue> Storage::Disk::CPM::GetCatalogue(
|
||||
int track = parameters.reserved_tracks;
|
||||
while(catalogue_allocation_bitmap) {
|
||||
if(catalogue_allocation_bitmap & 0x8000) {
|
||||
std::shared_ptr<Storage::Encodings::MFM::Sector> sector_contents = parser.get_sector(0, (uint8_t)track, (uint8_t)(parameters.first_sector + sector));
|
||||
if(!sector_contents) {
|
||||
return nullptr;
|
||||
}
|
||||
size_t size_read = 0;
|
||||
do {
|
||||
std::shared_ptr<Storage::Encodings::MFM::Sector> sector_contents = parser.get_sector(0, (uint8_t)track, (uint8_t)(parameters.first_sector + sector));
|
||||
if(!sector_contents) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
catalogue.insert(catalogue.end(), sector_contents->data.begin(), sector_contents->data.end());
|
||||
sector_size = sector_contents->data.size();
|
||||
catalogue.insert(catalogue.end(), sector_contents->data.begin(), sector_contents->data.end());
|
||||
sector_size = sector_contents->data.size();
|
||||
|
||||
size_read += sector_size;
|
||||
sector++;
|
||||
if(sector == parameters.sectors_per_track) {
|
||||
sector = 0;
|
||||
track++;
|
||||
}
|
||||
} while(size_read < (size_t)parameters.block_size);
|
||||
}
|
||||
|
||||
catalogue_allocation_bitmap <<= 1;
|
||||
|
||||
sector++;
|
||||
if(sector == parameters.sectors_per_track) {
|
||||
sector = 0;
|
||||
track++;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Catalogue> result(new Catalogue);
|
||||
|
Loading…
Reference in New Issue
Block a user