diff --git a/lib/imagewriter/imagewriter.cc b/lib/imagewriter/imagewriter.cc index 0d904b10..5d32c674 100644 --- a/lib/imagewriter/imagewriter.cc +++ b/lib/imagewriter/imagewriter.cc @@ -90,7 +90,7 @@ void ImageWriter::writeCsv(const std::string& filename) f << fmt::format("{},{},", track, head); const auto& sector = sectors.get(track, head, sectorId); if (!sector) - f << fmt::format(",,{},,,,,,,,MISSING\n", sectorId); + f << fmt::format(",,{},,,,,,,,sector not found\n", sectorId); else f << fmt::format("{},{},{},{},{},{},{},{},{},{},{}\n", sector->logicalTrack, diff --git a/lib/sector.cc b/lib/sector.cc index e72f292d..1b4da442 100644 --- a/lib/sector.cc +++ b/lib/sector.cc @@ -14,3 +14,18 @@ const std::string Sector::statusToString(Status status) default: return fmt::format("unknown error {}", status); } } + +Sector::Status Sector::stringToStatus(const std::string& value) +{ + if (value == "OK") + return Status::OK; + if (value == "bad checksum") + return Status::BAD_CHECKSUM; + if ((value == "sector not found") || (value == "MISSING")) + return Status::MISSING; + if (value == "present but no data found") + return Status::DATA_MISSING; + if (value == "conflicting data") + return Status::CONFLICT; + return Status::INTERNAL_ERROR; +} diff --git a/lib/sector.h b/lib/sector.h index c8fad300..8d2e6cd5 100644 --- a/lib/sector.h +++ b/lib/sector.h @@ -23,6 +23,7 @@ public: }; static const std::string statusToString(Status status); + static Status stringToStatus(const std::string& value); Status status = Status::INTERNAL_ERROR; Fluxmap::Position position; diff --git a/lib/sectorset.cc b/lib/sectorset.cc index fc059ada..efaea0a0 100644 --- a/lib/sectorset.cc +++ b/lib/sectorset.cc @@ -17,6 +17,18 @@ Sector* SectorSet::get(int track, int head, int sector) const return i->second.get(); } +Sector* SectorSet::add(int track, int head, int sector) +{ + key_t key(track, head, sector); + auto i = _data.find(key); + if (i != _data.end()) + return i->second.get(); + + Sector* s = new Sector; + _data[key].reset(s); + return s; +} + void SectorSet::calculateSize( unsigned& numTracks, unsigned& numHeads, unsigned& numSectors, unsigned& sectorSize) const diff --git a/lib/sectorset.h b/lib/sectorset.h index 6979b650..36189737 100644 --- a/lib/sectorset.h +++ b/lib/sectorset.h @@ -17,6 +17,8 @@ public: std::unique_ptr& get(int track, int head, int sector); Sector* get(int track, int head, int sector) const; + Sector* add(int track, int head, int sector); + const std::map>& get() const { return _data; } diff --git a/src/fe-analyselayout.cc b/src/fe-analyselayout.cc index 88f954cf..13fe8436 100644 --- a/src/fe-analyselayout.cc +++ b/src/fe-analyselayout.cc @@ -2,27 +2,112 @@ #include "flags.h" #include "dataspec.h" #include "fluxmap.h" +#include "sector.h" +#include "sectorset.h" +#include "csvreader.h" +#include "visualiser.h" #include "decoders/fluxmapreader.h" #include "dep/agg/include/agg2d.h" #include "dep/stb/stb_image_write.h" +#include "fmt/format.h" #include static FlagGroup flags = { + &visualiserFlags }; -static DataSpecFlag source( - { "--source", "-s" }, - "source for data", - ":d=0:t=0:s=0"); +static StringFlag source( + { "--csv", "-s" }, + "CSV file produced by reader", + ""); static DataSpecFlag writeImg( { "--write-img" }, "Draw a graph of the disk layout", ":w=640:h=480"); +static std::ifstream inputFile; + +static void check_for_error() +{ + if (inputFile.fail()) + Error() << fmt::format("I/O error: {}", strerror(errno)); +} + +static void bad_csv() +{ + Error() << "bad CSV file format"; +} + +static void readRow(const std::vector& row, SectorSet& sectors) +{ + if (row.size() != 13) + bad_csv(); + + try + { + Sector::Status status = Sector::stringToStatus(row[12]); + if (status == Sector::Status::INTERNAL_ERROR) + bad_csv(); + if (status == Sector::Status::MISSING) + return; + + int physicalTrack = std::stoi(row[0]); + int physicalSide = std::stoi(row[1]); + int logicalSector = std::stoi(row[4]); + + Sector* sector = sectors.add(physicalTrack, physicalSide, logicalSector); + sector->physicalTrack = physicalTrack; + sector->physicalSide = physicalSide; + sector->logicalTrack = std::stoi(row[2]); + sector->logicalSide = std::stoi(row[3]); + sector->logicalSector = logicalSector; + sector->clock = std::stod(row[5]); + sector->headerStartTime = std::stod(row[6]); + sector->headerEndTime = std::stod(row[7]); + sector->dataStartTime = std::stod(row[8]); + sector->dataEndTime = std::stod(row[9]); + sector->status = status; + } + catch (const std::invalid_argument& e) + { + bad_csv(); + } +} + +static SectorSet readCsv(const std::string& filename) +{ + if (filename == "") + Error() << "you must specify an input CSV file"; + + inputFile.open(filename); + check_for_error(); + + CsvReader csvReader(inputFile); + std::vector row = csvReader.readLine(); + if (row.size() != 13) + bad_csv(); + + SectorSet sectors; + for (;;) + { + row = csvReader.readLine(); + if (row.size() == 0) + break; + + readRow(row, sectors); + } + + return sectors; +} + int mainAnalyseLayout(int argc, const char* argv[]) { flags.parseFlags(argc, argv); + + SectorSet sectors = readCsv(source.get()); + visualiseSectorsToFile(sectors, "out.svg"); + return 0; }