Files
fluxengine/lib/dataspec.h
David Given 323da8272a Hopefully add support for giving the reader a set of required sectors, so if
one is missing then we can tell and the track can be reread.
2020-02-21 22:14:44 +01:00

153 lines
3.6 KiB
C++

#ifndef DATASPEC_H
#define DATASPEC_H
class MissingModifierException : public std::runtime_error
{
public:
MissingModifierException(const std::string& mod);
const std::string mod;
};
class DataSpec
{
public:
struct Modifier
{
std::string name;
std::set<unsigned> data;
std::string source;
bool operator == (const Modifier& other) const
{ return (name == other.name) && (data == other.data); }
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:
static std::vector<std::string> split(
const std::string& s, const std::string& delimiter);
static std::set<unsigned> parseRange(const std::string& spec);
static Modifier parseMod(const std::string& spec);
public:
DataSpec(const std::string& spec)
{ set(spec); }
void set(const std::string& spec);
operator std::string () const;
const Modifier& at(const std::string& mod) const;
bool has(const std::string& mod) const;
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;
};
class ImageSpec
{
public:
ImageSpec(const DataSpec& dataspec);
ImageSpec(const std::string filename,
unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes);
public:
std::string filename;
unsigned cylinders;
unsigned heads;
unsigned sectors;
unsigned bytes;
bool initialised : 1;
};
static inline std::ostream& operator << (std::ostream& os, const DataSpec& dataSpec)
{ os << (std::string)dataSpec; return os; }
class DataSpecFlag : public Flag
{
public:
DataSpecFlag(const std::vector<std::string>& names, const std::string helptext,
const std::string& defaultValue):
Flag(names, helptext),
_value(defaultValue)
{}
const DataSpec& get() const
{ checkInitialised(); return _value; }
operator const DataSpec& () const
{ return get(); }
bool hasArgument() const { return true; }
const std::string defaultValueAsString() const { return _value; }
void set(const std::string& value) { _value.set(value); }
private:
DataSpec _value;
};
class RangeFlag : public Flag
{
public:
RangeFlag(const std::vector<std::string>& names, const std::string helptext,
const std::string& defaultValue):
Flag(names, helptext),
_stringValue(defaultValue),
_value(DataSpec::parseRange(defaultValue))
{}
const std::set<unsigned>& get() const
{ checkInitialised(); return _value; }
operator const std::set<unsigned>& () const
{ return get(); }
bool hasArgument() const { return true; }
const std::string defaultValueAsString() const { return _stringValue; }
void set(const std::string& value)
{
_stringValue = value;
_value = DataSpec::parseRange(value);
}
private:
std::string _stringValue;
std::set<unsigned> _value;
};
#endif