Refactor dataspecs to allow them to be used for other things too.

This commit is contained in:
David Given
2019-08-06 23:50:02 +02:00
parent 28e0ef0463
commit eb924780ab
12 changed files with 160 additions and 73 deletions

View File

@@ -74,28 +74,54 @@ void DataSpec::set(const std::string& spec)
filename = words[0];
if (words.size() > 1)
{
locations.clear();
for (size_t i = 1; i < words.size(); i++)
{
auto mod = parseMod(words[i]);
if ((mod.name != "t") && (mod.name != "s") && (mod.name != "d"))
Error() << fmt::format("unknown data modifier '{}'", mod.name);
modifiers[mod.name] = mod;
}
}
}
const auto& drives = modifiers["d"].data;
FluxSpec::FluxSpec(const DataSpec& spec)
{
filename = spec.filename;
locations.clear();
const auto& drives = spec.modifiers.at("d").data;
if (drives.size() != 1)
Error() << "you must specify exactly one drive";
drive = *drives.begin();
const auto& tracks = modifiers["t"].data;
const auto& sides = modifiers["s"].data;
const auto& tracks = spec.modifiers.at("t").data;
const auto& sides = spec.modifiers.at("s").data;
for (auto track : tracks)
{
for (auto side : sides)
locations.push_back({ drive, track, side });
}
for (const auto& e : spec.modifiers)
{
const auto name = e.second.name;
if ((name != "t") && (name != "s") && (name != "d"))
Error() << fmt::format("unknown fluxspec modifier '{}'", name);
}
}
ImageSpec::ImageSpec(const DataSpec& spec)
{
filename = spec.filename;
tracks = spec.modifiers.at("t").only();
heads = spec.modifiers.at("h").only();
sectors = spec.modifiers.at("s").only();
for (const auto& e : spec.modifiers)
{
const auto name = e.second.name;
if ((name != "t") && (name != "h") && (name != "s"))
Error() << fmt::format("unknown fluxspec modifier '{}'", name);
}
}

View File

@@ -4,19 +4,6 @@
class DataSpec
{
public:
struct Location
{
unsigned drive;
unsigned track;
unsigned side;
bool operator == (const Location& other) const
{ return (drive == other.drive) && (track == other.track) && (side == other.side); }
bool operator != (const Location& other) const
{ return (drive != other.drive) || (track != other.track) || (side != other.side); }
};
struct Modifier
{
std::string name;
@@ -28,6 +15,13 @@ public:
bool operator != (const Modifier& other) const
{ return (name != other.name) || (data != other.data); }
unsigned only() const
{
if (data.size() != 1)
Error() << "modifier " << name << " can only have one value";
return *(data.begin());
}
};
public:
@@ -44,9 +38,43 @@ public:
std::string filename;
std::map<std::string, Modifier> modifiers;
};
class FluxSpec
{
public:
struct Location
{
unsigned drive;
unsigned track;
unsigned side;
bool operator == (const Location& other) const
{ return (drive == other.drive) && (track == other.track) && (side == other.side); }
bool operator != (const Location& other) const
{ return (drive != other.drive) || (track != other.track) || (side != other.side); }
};
public:
FluxSpec(const DataSpec& dataspec);
public:
std::string filename;
std::vector<Location> locations;
unsigned drive;
unsigned revolutions;
};
class ImageSpec
{
public:
ImageSpec(const DataSpec& dataspec);
public:
std::string filename;
unsigned tracks;
unsigned heads;
unsigned sectors;
};
static inline std::ostream& operator << (std::ostream& os, const DataSpec& dataSpec)

View File

@@ -10,7 +10,7 @@ static bool ends_with(const std::string& value, const std::string& ending)
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
std::unique_ptr<FluxSink> FluxSink::create(const DataSpec& spec)
std::unique_ptr<FluxSink> FluxSink::create(const FluxSpec& spec)
{
const auto& filename = spec.filename;

View File

@@ -2,7 +2,7 @@
#define FLUXSINK_H
class Fluxmap;
class DataSpec;
class FluxSpec;
class FluxSink
{
@@ -14,7 +14,7 @@ private:
static std::unique_ptr<FluxSink> createHardwareFluxSink(unsigned drive);
public:
static std::unique_ptr<FluxSink> create(const DataSpec& spec);
static std::unique_ptr<FluxSink> create(const FluxSpec& spec);
public:
virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0;

View File

@@ -10,7 +10,7 @@ static bool ends_with(const std::string& value, const std::string& ending)
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
std::unique_ptr<FluxSource> FluxSource::create(const DataSpec& spec)
std::unique_ptr<FluxSource> FluxSource::create(const FluxSpec& spec)
{
const auto& filename = spec.filename;

View File

@@ -6,7 +6,7 @@
extern FlagGroup hardwareFluxSourceFlags;
class Fluxmap;
class DataSpec;
class FluxSpec;
class FluxSource
{
@@ -19,7 +19,7 @@ private:
static std::unique_ptr<FluxSource> createStreamFluxSource(const std::string& path);
public:
static std::unique_ptr<FluxSource> create(const DataSpec& spec);
static std::unique_ptr<FluxSource> create(const FluxSpec& spec);
public:
virtual std::unique_ptr<Fluxmap> readFlux(int track, int side) = 0;

View File

@@ -71,9 +71,9 @@ void Track::readFluxmap()
std::vector<std::unique_ptr<Track>> readTracks()
{
const DataSpec& dataSpec = source;
const FluxSpec spec(source);
std::cout << "Reading from: " << dataSpec << std::endl;
std::cout << "Reading from: " << source << std::endl;
setHardwareFluxSourceDensity(highDensityFlag);
@@ -92,10 +92,10 @@ std::vector<std::unique_ptr<Track>> readTracks()
);
}
std::shared_ptr<FluxSource> fluxSource = FluxSource::create(dataSpec);
std::shared_ptr<FluxSource> fluxSource = FluxSource::create(spec);
std::vector<std::unique_ptr<Track>> tracks;
for (const auto& location : dataSpec.locations)
for (const auto& location : spec.locations)
{
auto track = std::make_unique<Track>(location.track, location.side);
track->fluxsource = fluxSource;

View File

@@ -36,9 +36,9 @@ void setWriterDefaultDest(const std::string& dest)
void writeTracks(
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
{
const DataSpec& spec = dest;
const FluxSpec spec(dest);
std::cout << "Writing to: " << spec << std::endl;
std::cout << "Writing to: " << dest << std::endl;
setHardwareFluxSourceDensity(highDensityFlag);
setHardwareFluxSinkDensity(highDensityFlag);

View File

@@ -34,14 +34,15 @@ int mainConvertFluxToAu(int argc, const char* argv[])
{
flags.parseFlags(argc, argv);
const auto& locations = source.get().locations;
FluxSpec spec(source);
const auto& locations = spec.locations;
if (locations.size() != 1)
Error() << "the source dataspec must contain exactly one track (two sides count as two tracks)";
const auto& location = *(locations.begin());
std::cerr << "Reading source flux...\n";
setHardwareFluxSourceDensity(highDensityFlag);
std::shared_ptr<FluxSource> fluxsource = FluxSource::create(source);
std::shared_ptr<FluxSource> fluxsource = FluxSource::create(spec);
const auto& fluxmap = fluxsource->readFlux(location.track, location.side);
unsigned totalTicks = fluxmap->ticks() + 2;
unsigned channels = withIndex ? 2 : 1;

View File

@@ -30,14 +30,15 @@ int mainConvertFluxToVcd(int argc, const char* argv[])
{
flags.parseFlags(argc, argv);
const auto& locations = source.get().locations;
const FluxSpec spec(source);
const auto& locations = spec.locations;
if (locations.size() != 1)
Error() << "the source dataspec must contain exactly one track (two sides count as two tracks)";
const auto& location = *(locations.begin());
std::cerr << "Reading source flux...\n";
setHardwareFluxSourceDensity(highDensityFlag);
std::shared_ptr<FluxSource> fluxsource = FluxSource::create(source);
std::shared_ptr<FluxSource> fluxsource = FluxSource::create(spec);
const auto& fluxmap = fluxsource->readFlux(location.track, location.side);
std::cerr << "Writing destination VCD...\n";

View File

@@ -14,7 +14,8 @@ int mainRpm(int argc, const char* argv[])
{
flags.parseFlags(argc, argv);
usbSetDrive(source.get().drive, false);
FluxSpec spec(source);
usbSetDrive(spec.drive, false);
nanoseconds_t period = usbGetRotationalPeriod();
std::cout << "Rotational period is " << period/1000 << " ms (" << 60e6/period << " rpm)" << std::endl;

View File

@@ -33,48 +33,78 @@ static void test_parsemod(void)
== (DataSpec::Modifier{"x", {2, 4, 9}}));
}
static void test_dataspec(void)
static void test_fluxspec(void)
{
DataSpec spec("foo:t=0-2:s=0-1:d=0");
assert(spec.filename == "foo");
assert((spec.locations
== std::vector<DataSpec::Location>
{
FluxSpec fspec(spec);
assert(fspec.filename == "foo");
assert((fspec.locations
== std::vector<FluxSpec::Location>
{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {0, 2, 0}, {0, 2, 1}}));
assert((std::string)spec == "foo:d=0:s=0-1:t=0-2");
}
spec.set("bar");
assert(spec.filename == "bar");
assert((spec.locations
== std::vector<DataSpec::Location>
{
FluxSpec fspec(spec);
assert(fspec.filename == "bar");
assert((fspec.locations
== std::vector<FluxSpec::Location>
{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {0, 2, 0}, {0, 2, 1}}));
assert((std::string)spec == "bar:d=0:s=0-1:t=0-2");
}
spec.set(":t=0");
assert(spec.filename.empty());
assert((spec.locations
== std::vector<DataSpec::Location>
{
FluxSpec fspec(spec);
assert(fspec.filename.empty());
assert((fspec.locations
== std::vector<FluxSpec::Location>
{{0, 0, 0}, {0, 0, 1}}));
assert((std::string)spec == ":d=0:s=0-1:t=0");
}
spec.set(":s=1");
assert(spec.filename.empty());
assert((spec.locations
== std::vector<DataSpec::Location>
{
FluxSpec fspec(spec);
assert(fspec.filename.empty());
assert((fspec.locations
== std::vector<FluxSpec::Location>
{{0, 0, 1}}));
assert((std::string)spec == ":d=0:s=1:t=0");
}
spec.set(":t=9:d=1");
assert(spec.filename.empty());
assert((spec.locations
== std::vector<DataSpec::Location>
{
FluxSpec fspec(spec);
assert(fspec.filename.empty());
assert((fspec.locations
== std::vector<FluxSpec::Location>
{{1, 9, 1}}));
assert((std::string)spec == ":d=1:s=1:t=9");
}
}
static void test_imagespec(void)
{
DataSpec spec("foo:t=9:h=2:s=99");
{
ImageSpec ispec(spec);
assert(ispec.filename == "foo");
assert(ispec.tracks == 9);
assert(ispec.heads == 2);
assert(ispec.sectors == 99);
}
}
int main(int argc, const char* argv[])
{
test_split();
test_parsemod();
test_dataspec();
test_fluxspec();
test_imagespec();
return 0;
}