Refactor for robustness and clarity
This commit is contained in:
parent
8c04650caf
commit
6603f96d69
@ -6,6 +6,6 @@ Project 2 for CSCE4600, for Team G4
|
|||||||
|
|
||||||
Build with `make`
|
Build with `make`
|
||||||
|
|
||||||
Run with `make run`
|
Run with `./main.out filename`
|
||||||
|
|
||||||
Clean with `make clean`
|
Clean with `make clean`
|
||||||
|
@ -11,9 +11,8 @@ public:
|
|||||||
graph() {}
|
graph() {}
|
||||||
// Initializers:
|
// Initializers:
|
||||||
// Read a graph from a file
|
// Read a graph from a file
|
||||||
void read(std::string filename);
|
int read(std::string filename);
|
||||||
// TODO: generate a random graph
|
|
||||||
void random(int processes, int resources);
|
|
||||||
// check functions:
|
// check functions:
|
||||||
// is the graph...
|
// is the graph...
|
||||||
bool reducible();// ?
|
bool reducible();// ?
|
||||||
@ -23,17 +22,13 @@ public:
|
|||||||
// print the graph
|
// print the graph
|
||||||
void print ();
|
void print ();
|
||||||
|
|
||||||
struct m{
|
typedef std::vector<std::vector<int>> matrix;
|
||||||
int x, y;
|
|
||||||
std::vector<std::vector<int>> data;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int num_processes = 0;
|
int num_processes = 0;
|
||||||
int num_resources = 0;
|
int num_resources = 0;
|
||||||
std::vector<int> resource_counts;
|
std::vector<int> resource_counts;
|
||||||
struct m matrix; // Tell me, Mr. Anderson, what good is a phone call if you are unable to speak?
|
matrix m; // Tell me, Mr. Anderson, what good is a phone call if you are unable to speak?
|
||||||
bool is_blocked(int process_id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -6,7 +6,7 @@
|
|||||||
#include "graph.hpp"
|
#include "graph.hpp"
|
||||||
|
|
||||||
void graph::print () {
|
void graph::print () {
|
||||||
printf("np: %d\tnr: %d\n", num_processes, num_resources);
|
printf("num_processes: %d\nnum_resources: %d\n", num_processes, num_resources);
|
||||||
printf("resource_counts:\n"); for (auto e: resource_counts) printf("%d\t", e); printf("\n");
|
printf("resource_counts: ["); for (auto e: resource_counts) printf("%d, ", e); printf("\b\b]\n");
|
||||||
printf("matrix:\n"); for (auto x: matrix.data) {for (auto y: x) printf("%d\t", y); printf("\n");}
|
printf("matrix:\n| "); for (auto x: m) {for (auto y: x) printf("%d, ", y); printf("\b\b |\n| ");} printf("\b\b \b\b");
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,14 @@ int main(int argc, char** argv) {
|
|||||||
graph g;
|
graph g;
|
||||||
|
|
||||||
//TODO: Implement reading from a file
|
//TODO: Implement reading from a file
|
||||||
g.read(filename);
|
int err = g.read(filename);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
g.print();
|
g.print();
|
||||||
|
|
||||||
// TODO: Implement graph reduction and/or knot detection
|
// 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
|
// TODO: Destroy the graph created by read_file
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -7,45 +7,51 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include "graph.hpp"
|
#include "graph.hpp"
|
||||||
|
|
||||||
#define MAX_INT_LEN 16
|
//* Vector of regex rules, in order of precedence. Earlier entries will be checked before later entries.
|
||||||
|
|
||||||
// Vector of regices, in order of precedence. Earlier entries will be checked before later entries.
|
|
||||||
std::vector<std::regex> patterns = {
|
std::vector<std::regex> patterns = {
|
||||||
//* Rule 1: A line starting with a % is a comment, and should not be parsed
|
//* Rule 1: A line containing % is a comment, and should not be parsed
|
||||||
std::regex("^\\s*(%)"),
|
std::regex("(%)"),
|
||||||
//* Rule 2: A line starting with `num_processes=` contains the number of processes
|
//* Rule 2: A line containing `num_processes` contains the number of processes
|
||||||
std::regex("^.*(num_processes)\\s*=\\s*(\\d+).*"),
|
std::regex("(num_processes)\\D*(\\d+)"),
|
||||||
//* Rule 3: A line starting with `num_resources=` contains the number of resources
|
//* Rule 3: A line containing `num_resources` contains the number of resources
|
||||||
std::regex("^.*(num_resources)\\s*=\\s*(\\d+)"),
|
std::regex("(num_resources)\\D*(\\d+)"),
|
||||||
//* Rule 4: A line containing only comma-separated values should be captured completely
|
//* Rule 4: A line containing integers should be saved somewhere
|
||||||
std::regex("^([\\-0-9, ]+)") // matches comma-separated space-separated signed decimal integers
|
std::regex("(-?[0-9]+.*-?[0-9]+)") // Magical!
|
||||||
};
|
};
|
||||||
|
|
||||||
// convert comma-separated string s to vector<int>
|
// Say hi to Stovey, here to bake your cakes.
|
||||||
std::vector<int> stovi (const std::string &s);
|
//* convert string s to vector<int> no matter the cost
|
||||||
|
std::vector<int> stovi (const std::string &s) {
|
||||||
// TODO: Implement reading from a file
|
// Create the number classification rule
|
||||||
void graph::read(std::string filename) {
|
std::regex rule("-?[0-9]+");
|
||||||
|
// Make a new tokenizing iterator using the rule
|
||||||
// Open file with name filename as read-only
|
std::sregex_token_iterator start{s.begin(), s.end(), rule, 0}, end;
|
||||||
std::fstream f; f.open(filename, f.in);
|
// Match the numbers
|
||||||
// TODO: Check for file IO errors (I might have a solution for that in another project)
|
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()) {
|
while (!f.eof()) {
|
||||||
// acquire a line
|
// acquire a line
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline (f, line);
|
std::getline (f, line);
|
||||||
|
|
||||||
// Iterate over each pattern, and grab the associated data
|
// Iterate over each pattern, and grab the associated data
|
||||||
for (auto pattern: patterns) {
|
for (const auto &pattern: patterns) {
|
||||||
std::smatch res;
|
std::smatch res;
|
||||||
|
// Capture data with a regex search, using the pattern
|
||||||
if (std::regex_search (line, res, pattern)) {
|
if (std::regex_search (line, res, pattern)) {
|
||||||
// get the pattern type, value
|
// get the pattern type, value
|
||||||
std::string type = res.format("$1"), value = res.format("$2");
|
std::string type = res.format("$1"), value = res.format("$2");
|
||||||
// Handle the pattern
|
// Handle the pattern
|
||||||
// Rule 1: If line is a comment, ignore it and move on
|
// 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
|
// Rule 2: If num_processes= matched, assign value to num_processes
|
||||||
if (type == "num_processes") { num_processes = std::stoi(value); } else
|
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
|
// Rule 3: If num_resources= matched, assign value to num_resources
|
||||||
if (type == "num_resources") { num_resources = std::stoi(value); } else
|
if (type == "num_resources") { num_resources = std::stoi(value); } else
|
||||||
|
|
||||||
// Rule 4: If this line is a comma-separated list of numbers,
|
// Rule 4: If this line is a comma-separated list of numbers:
|
||||||
// and this is the first match, assign it to resource counts
|
// 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
|
if (!resource_counts.size()) { resource_counts = stovi(type); } else
|
||||||
// and this is a subsequent match, push it onto the matrix
|
{ m.push_back(stovi(type)); }
|
||||||
{ matrix.data.push_back(stovi(type)); }
|
|
||||||
|
|
||||||
// If a pattern is matched, go to the next line and skip evaluating other patterns
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close file
|
//* Test validity of the input file
|
||||||
f.close();
|
// Check if all sections are properly defined:
|
||||||
// TODO: Check for file IO errors (Shouldn't be any)
|
const char errmsg[] = "%s: Definition failed for %s\n";
|
||||||
|
int ret = 0;
|
||||||
return;
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> stovi (const std::string &s) {
|
// fstream destructor closes file when going out of scope
|
||||||
// Create the number classifier
|
// in this house we RAII sometimes.
|
||||||
std::regex pattern("[0-9]+");
|
return ret;
|
||||||
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;
|
|
||||||
}
|
}
|
29
test1.txt
29
test1.txt
@ -1,13 +1,14 @@
|
|||||||
% This file is a very poorly formatted example file, which contains all sorts of garbage
|
% This file is a very poorly formatted example file, which contains all sorts of garbage
|
||||||
% This was written to ensure the parser is as robust as possible, and won't crash on malformed input
|
% This was written to stress-test the parser
|
||||||
|
|
||||||
nv249hvbwer8oysbvdofuvbfdz wsdfabsv num_processes = 4
|
this is horrible to read!
|
||||||
// Gee, this isn't actually a comment is it?
|
nv249hvbwer8oysbvdofuvbfdzwsdfabsvnum_processesbgskjhdfd=lbahfbzjhxbc,4gsv4wf5fewf6, 7, 8
|
||||||
# but most of that is there to distract the program!
|
^^^^ Believe it or not, this is a num_processes line! ^^^^
|
||||||
|
// Gee, this isn't actually a comment is it? As long as I don't include a number, it won't care.
|
||||||
[][][][]\\\\\';./` num_resources= 4ibeoifbavdivbkdhbz
|
[][][][]\\\\\';./` num_resources= 4ibeoifbavdivbkdhbz
|
||||||
% lines beginning with % are comments
|
% lines containing % are comments
|
||||||
% for example: num_processes = 128314
|
for example: num_processes = 128314%
|
||||||
% The first line containing a list of numbers will be interpreted as resource_counts
|
% The first non-comment line containing a list of numbers will be interpreted as resource_counts
|
||||||
12 ,14,16 , 18
|
12 ,14,16 , 18
|
||||||
% this line is missing a comma
|
% this line is missing a comma
|
||||||
1,2 3,4,5,6,7,8
|
1,2 3,4,5,6,7,8
|
||||||
@ -16,8 +17,12 @@ nv249hvbwer8oysbvdofuvbfdz wsdfabsv num_processes = 4
|
|||||||
% and this one, before the comma
|
% and this one, before the comma
|
||||||
1 ,2 ,3 ,4 ,5 ,6 ,7,8
|
1 ,2 ,3 ,4 ,5 ,6 ,7,8
|
||||||
% nevertheless, it keeps on chugging.
|
% nevertheless, it keeps on chugging.
|
||||||
1,2,3,4,5,6,7,8
|
~~~1~~~2~~~3~~~4~~~5~~~6~~~7~~~8~~~
|
||||||
1,2,3,4,5,6,7,8
|
1a 2b 3c, 4d 5e 6f, 7g 8h
|
||||||
1,2,3,4,5,6,7,8
|
^^^^ Testing mixed letters and numbers ^^^^
|
||||||
1,2,3,4,5,6,7,8
|
@Xx_1_2_3_4_5_6_7_8_()_xX#
|
||||||
1,2,3,4,5,6,7,8
|
words, words, words!
|
||||||
|
|
||||||
|
vvvv testing negative numbers vvvv
|
||||||
|
1,-2,3,4,5,6,-7,8
|
||||||
|
-1,2,3,4,5,6,7,-8
|
Loading…
Reference in New Issue
Block a user