Refactor for robustness and clarity

This commit is contained in:
2022-04-23 04:47:55 -05:00
parent 8c04650caf
commit 6603f96d69
6 changed files with 97 additions and 72 deletions

View File

@@ -6,7 +6,7 @@
#include "graph.hpp"
void graph::print () {
printf("np: %d\tnr: %d\n", num_processes, num_resources);
printf("resource_counts:\n"); for (auto e: resource_counts) printf("%d\t", e); printf("\n");
printf("matrix:\n"); for (auto x: matrix.data) {for (auto y: x) printf("%d\t", y); printf("\n");}
printf("num_processes: %d\nnum_resources: %d\n", num_processes, num_resources);
printf("resource_counts: ["); for (auto e: resource_counts) printf("%d, ", e); printf("\b\b]\n");
printf("matrix:\n| "); for (auto x: m) {for (auto y: x) printf("%d, ", y); printf("\b\b |\n| ");} printf("\b\b \b\b");
}

View File

@@ -15,11 +15,14 @@ int main(int argc, char** argv) {
graph g;
//TODO: Implement reading from a file
g.read(filename);
int err = g.read(filename);
if (err) {
return err;
}
g.print();
// TODO: Implement graph reduction and/or knot detection
printf("Graph is %s\n", g.reducible()?"not reducible (deadlock!)":"reducible (no deadlock!)");//?
printf("Graph is %s\n", g.reducible()?"not reducible! Deadlock!":"reducible! No deadlock!");//?
// TODO: Destroy the graph created by read_file
return 0;

View File

@@ -7,45 +7,51 @@
#include <regex>
#include "graph.hpp"
#define MAX_INT_LEN 16
// Vector of regices, in order of precedence. Earlier entries will be checked before later entries.
//* Vector of regex rules, in order of precedence. Earlier entries will be checked before later entries.
std::vector<std::regex> patterns = {
//* Rule 1: A line starting with a % is a comment, and should not be parsed
std::regex("^\\s*(%)"),
//* Rule 2: A line starting with `num_processes=` contains the number of processes
std::regex("^.*(num_processes)\\s*=\\s*(\\d+).*"),
//* Rule 3: A line starting with `num_resources=` contains the number of resources
std::regex("^.*(num_resources)\\s*=\\s*(\\d+)"),
//* Rule 4: A line containing only comma-separated values should be captured completely
std::regex("^([\\-0-9, ]+)") // matches comma-separated space-separated signed decimal integers
//* Rule 1: A line containing % is a comment, and should not be parsed
std::regex("(%)"),
//* Rule 2: A line containing `num_processes` contains the number of processes
std::regex("(num_processes)\\D*(\\d+)"),
//* Rule 3: A line containing `num_resources` contains the number of resources
std::regex("(num_resources)\\D*(\\d+)"),
//* Rule 4: A line containing integers should be saved somewhere
std::regex("(-?[0-9]+.*-?[0-9]+)") // Magical!
};
// convert comma-separated string s to vector<int>
std::vector<int> stovi (const std::string &s);
// TODO: Implement reading from a file
void graph::read(std::string filename) {
// Open file with name filename as read-only
std::fstream f; f.open(filename, f.in);
// TODO: Check for file IO errors (I might have a solution for that in another project)
// Say hi to Stovey, here to bake your cakes.
//* convert string s to vector<int> no matter the cost
std::vector<int> stovi (const std::string &s) {
// Create the number classification rule
std::regex rule("-?[0-9]+");
// Make a new tokenizing iterator using the rule
std::sregex_token_iterator start{s.begin(), s.end(), rule, 0}, end;
// Match the numbers
std::vector<int> res;
for (auto i = start; i != end; ++i) res.push_back(atoi(i->str().c_str()));
// give the numbers back
return res;
}
//* Read from a file of name `filename`
int graph::read(std::string filename) {
// Open file with name filename as input fstream
std::ifstream f(filename);
// Read the entire file
while (!f.eof()) {
// acquire a line
std::string line;
std::getline (f, line);
// Iterate over each pattern, and grab the associated data
for (auto pattern: patterns) {
for (const auto &pattern: patterns) {
std::smatch res;
// Capture data with a regex search, using the pattern
if (std::regex_search (line, res, pattern)) {
// get the pattern type, value
std::string type = res.format("$1"), value = res.format("$2");
// Handle the pattern
// Rule 1: If line is a comment, ignore it and move on
if (type == "%"); else
if (type == "%") break;
// Rule 2: If num_processes= matched, assign value to num_processes
if (type == "num_processes") { num_processes = std::stoi(value); } else
@@ -53,32 +59,48 @@ void graph::read(std::string filename) {
// Rule 3: If num_resources= matched, assign value to num_resources
if (type == "num_resources") { num_resources = std::stoi(value); } else
// Rule 4: If this line is a comma-separated list of numbers,
// and this is the first match, assign it to resource counts
// Rule 4: If this line is a comma-separated list of numbers:
// If resource_counts is empty, assume this is the resource counts,
// else it's part of the matrix being reloaded
if (!resource_counts.size()) { resource_counts = stovi(type); } else
// and this is a subsequent match, push it onto the matrix
{ matrix.data.push_back(stovi(type)); }
// If a pattern is matched, go to the next line and skip evaluating other patterns
{ m.push_back(stovi(type)); }
break;
}
}
}
// Close file
f.close();
// TODO: Check for file IO errors (Shouldn't be any)
//* Test validity of the input file
// Check if all sections are properly defined:
const char errmsg[] = "%s: Definition failed for %s\n";
int ret = 0;
if (!num_processes){
printf(errmsg, filename.c_str(), "num_processes");
ret |= 0b00001;
}
if (!num_resources){
printf(errmsg, filename.c_str(), "num_resources");
ret |= 0b00010;
}
if (resource_counts.size() != num_resources){
printf(errmsg, filename.c_str(), "resource counts");
ret |= 0b00100;
}
if (m.size() != num_processes + num_resources){
printf(errmsg, filename.c_str(), "adjacency matrix rows");
ret |= 0b01000;
}
for (auto i: m) {
if (i.size() != num_processes + num_resources)
ret |= 0b10000;
}
if (ret & 0b10000) {
printf(errmsg, filename.c_str(), "adjacency matrix columns");
}
if (ret) {
printf("Check to ensure your input file is correct and follows the Rules.\n");
}
return;
}
std::vector<int> stovi (const std::string &s) {
// Create the number classifier
std::regex pattern("[0-9]+");
std::sregex_token_iterator first{s.begin(), s.end(), pattern, 0}, last;
// Match the numbers
std::vector<int> res;
for (auto i = first; i != last; ++i) res.push_back(atoi(i->str().c_str()));
// give the numbers back
return res;
// fstream destructor closes file when going out of scope
// in this house we RAII sometimes.
return ret;
}