Refactor the way image extensions are handled to be generally cleaner. Add

support for validating ImageSpecs before we actually want to read/write an
image, so as to allow us to check the extension *before* wasting time reading a
disk. Make .d81 an alias of .img.
This commit is contained in:
David Given
2019-08-21 00:45:10 +02:00
parent 28d0ce765e
commit 60bfe050d3
6 changed files with 80 additions and 16 deletions

View File

@@ -22,7 +22,7 @@ extern void hexdumpForSrp16(std::ostream& stream, const Bytes& bytes);
class Error class Error
{ {
public: public:
~Error() [[ noreturn ]] ~Error()
{ {
std::cerr << "Error: " << _stream.str() << std::endl; std::cerr << "Error: " << _stream.str() << std::endl;
exit(1); exit(1);

View File

@@ -7,6 +7,13 @@
#include "imagereader/imagereader.h" #include "imagereader/imagereader.h"
#include "fmt/format.h" #include "fmt/format.h"
std::map<std::string, ImageReader::Constructor> ImageReader::formats =
{
{".adf", ImageReader::createImgImageReader},
{".d81", ImageReader::createImgImageReader},
{".img", ImageReader::createImgImageReader},
};
static bool ends_with(const std::string& value, const std::string& ending) static bool ends_with(const std::string& value, const std::string& ending)
{ {
if (ending.size() > value.size()) if (ending.size() > value.size())
@@ -14,15 +21,29 @@ static bool ends_with(const std::string& value, const std::string& ending)
return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
} }
std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec) ImageReader::Constructor ImageReader::findConstructor(const ImageSpec& spec)
{ {
const auto& filename = spec.filename; const auto& filename = spec.filename;
if (ends_with(filename, ".img") || ends_with(filename, ".adf")) for (const auto& e : formats)
return createImgImageReader(spec); {
if (ends_with(filename, e.first))
return e.second;
}
Error() << "unrecognised image filename extension"; return NULL;
return std::unique_ptr<ImageReader>(); }
std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec)
{
verifyImageSpec(spec);
return findConstructor(spec)(spec);
}
void ImageReader::verifyImageSpec(const ImageSpec& spec)
{
if (!findConstructor(spec))
Error() << "unrecognised image filename extension";
} }
ImageReader::ImageReader(const ImageSpec& spec): ImageReader::ImageReader(const ImageSpec& spec):

View File

@@ -12,10 +12,21 @@ public:
public: public:
static std::unique_ptr<ImageReader> create(const ImageSpec& spec); static std::unique_ptr<ImageReader> create(const ImageSpec& spec);
static void verifyImageSpec(const ImageSpec& spec);
private: private:
typedef
std::function<
std::unique_ptr<ImageReader>(const ImageSpec& spec)
>
Constructor;
static std::map<std::string, Constructor> formats;
static std::unique_ptr<ImageReader> createImgImageReader(const ImageSpec& spec); static std::unique_ptr<ImageReader> createImgImageReader(const ImageSpec& spec);
static Constructor findConstructor(const ImageSpec& spec);
public: public:
virtual SectorSet readImage() = 0; virtual SectorSet readImage() = 0;

View File

@@ -7,6 +7,15 @@
#include "imagewriter/imagewriter.h" #include "imagewriter/imagewriter.h"
#include "fmt/format.h" #include "fmt/format.h"
std::map<std::string, ImageWriter::Constructor> ImageWriter::formats =
{
{".adf", ImageWriter::createImgImageWriter},
{".d64", ImageWriter::createD64ImageWriter},
{".d81", ImageWriter::createImgImageWriter},
{".img", ImageWriter::createImgImageWriter},
{".ldbs", ImageWriter::createLDBSImageWriter},
};
static bool ends_with(const std::string& value, const std::string& ending) static bool ends_with(const std::string& value, const std::string& ending)
{ {
if (ending.size() > value.size()) if (ending.size() > value.size())
@@ -14,19 +23,29 @@ static bool ends_with(const std::string& value, const std::string& ending)
return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
} }
std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec) ImageWriter::Constructor ImageWriter::findConstructor(const ImageSpec& spec)
{ {
const auto& filename = spec.filename; const auto& filename = spec.filename;
if (ends_with(filename, ".img") || ends_with(filename, ".adf")) for (const auto& e : formats)
return createImgImageWriter(sectors, spec); {
else if (ends_with(filename, ".ldbs")) if (ends_with(filename, e.first))
return createLDBSImageWriter(sectors, spec); return e.second;
else if (ends_with(filename, ".d64")) }
return createD64ImageWriter(sectors, spec);
Error() << "unrecognised image filename extension"; return NULL;
return std::unique_ptr<ImageWriter>(); }
std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec)
{
verifyImageSpec(spec);
return findConstructor(spec)(sectors, spec);
}
void ImageWriter::verifyImageSpec(const ImageSpec& spec)
{
if (!findConstructor(spec))
Error() << "unrecognised image filename extension";
} }
ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec): ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec):

View File

@@ -12,8 +12,17 @@ public:
public: public:
static std::unique_ptr<ImageWriter> create(const SectorSet& sectors, const ImageSpec& spec); static std::unique_ptr<ImageWriter> create(const SectorSet& sectors, const ImageSpec& spec);
static void verifyImageSpec(const ImageSpec& filename);
private: private:
typedef
std::function<
std::unique_ptr<ImageWriter>(const SectorSet& sectors, const ImageSpec& spec)
>
Constructor;
static std::map<std::string, Constructor> formats;
static std::unique_ptr<ImageWriter> createImgImageWriter( static std::unique_ptr<ImageWriter> createImgImageWriter(
const SectorSet& sectors, const ImageSpec& spec); const SectorSet& sectors, const ImageSpec& spec);
static std::unique_ptr<ImageWriter> createLDBSImageWriter( static std::unique_ptr<ImageWriter> createLDBSImageWriter(
@@ -21,6 +30,8 @@ private:
static std::unique_ptr<ImageWriter> createD64ImageWriter( static std::unique_ptr<ImageWriter> createD64ImageWriter(
const SectorSet& sectors, const ImageSpec& spec); const SectorSet& sectors, const ImageSpec& spec);
static Constructor findConstructor(const ImageSpec& spec);
public: public:
virtual void adjustGeometry(); virtual void adjustGeometry();
void printMap(); void printMap();

View File

@@ -14,6 +14,7 @@
#include "bytes.h" #include "bytes.h"
#include "decoders/rawbits.h" #include "decoders/rawbits.h"
#include "track.h" #include "track.h"
#include "imagewriter/imagewriter.h"
#include "fmt/format.h" #include "fmt/format.h"
FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags }; FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags };
@@ -153,6 +154,7 @@ static void replace_sector(std::unique_ptr<Sector>& replacing, Sector& replaceme
void readDiskCommand(AbstractDecoder& decoder) void readDiskCommand(AbstractDecoder& decoder)
{ {
const ImageSpec outputSpec(output); const ImageSpec outputSpec(output);
ImageWriter::verifyImageSpec(outputSpec);
bool failures = false; bool failures = false;
SectorSet allSectors; SectorSet allSectors;