ContigousMemory / Main.cpp
Main.cpp
Raw
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <vector>
#include "memories/FirstFitMemory.cpp"
#include "memories/BestFitMemory.cpp"
#include "memories/WorstFitMemory.cpp"
using namespace std;

#define MAX_ARGS 3


/*****************************************************************************
 * This function parses a line from instruction file, into usable arguments. *
 * Maximum of 3 args for 'A' instruction.                                    *
 *****************************************************************************/ 

vector<string> extractInst(string line, string delimiter){

  vector<string> args;
    // Loop to split the line (use delimiter) into individual args.
  for (int i=0; i < MAX_ARGS; i++){
    string curr_inst = line.substr(0, line.find(delimiter));
    curr_inst = curr_inst.substr(0, line.find("\r"));
    args.push_back(curr_inst);
    line.erase(0, line.find(delimiter) + delimiter.length());
  }
  return args;
};


/*********************************************************************
 * Checks the argument for wrong data type/format and illegal chars. *
**********************************************************************/
bool parsingHasIssues(string arg){
  // Check for chars that are not numbers
  for(char c : arg){
    if(!isdigit(c)){
      return true;
    }
  };

  // All positions are digits.
  return false;
};



/*****************************************************************
 * Convert a memory block into text to save its state in a file. *
******************************************************************/
string blockToText(MemBlock* block){
  string temp;
  if(block->getId() >= 0){
    // Program
    temp = to_string(block->getId()) + ";" + to_string(block->getStart()) + ";" + to_string(block->getEnd()) + "\n";
  } else {
    // Hole
    temp = to_string(block->getStart()) + ";" + to_string(block->getEnd()) + "\n";
  };
  return temp;
};


/**********************************
 * Sorting condition for Snapshot *
***********************************/
bool compareBlockId(MemBlock* b1, MemBlock* b2){
  return (b1->getId() < b2->getId());
};

/***************************************************************************
* This function takes a snapshot of the memory when "O" command is called. *
****************************************************************************/
void makeSnapshot(FauxMemory* mem, ofstream* file, string strategy){
  // Add a header
  (*file) << strategy + "\n";


  // Categorise blocks
  vector<MemBlock*> holes;
  vector<MemBlock*> programs;

  for(auto block : (*mem->getAllBlocks())){
    if (block->getId() >= 0){programs.push_back(block);}
    else{holes.push_back(block);};
  }; 


  // Sort program blocks by ID
  sort(programs.begin(), programs.end(), compareBlockId);


  // Write blocks to file
    // Program blocks
  (*file) << "Allocated blocks\n";
  for(auto program : programs){
    (*file) << blockToText(program);
  };
    // Hole blocks
  (*file) << "Free blocks\n";
  for(auto hole : holes){
    (*file) << blockToText(hole);
  };


  // Fragmentation
  (*file) << "Fragmentation\n";
  (*file) << to_string(mem->fragmentation()) << "\n";
  
  // Errors
  (*file) << "Errors\n";
  if((*mem->getAllErrors()).size() == 0){
    (*file) << "None\n";
  }else{
    for(auto error : (*mem->getAllErrors())){
      (*file) << error << "\n";
    };
  };
};


/*********************************
* Main simulation of the memory. *
**********************************/
int main(int argc, char *argv[]){
  // Check args for file name
  if(argc != 2){
    cout << "Usage: ./Main instruction_file.in";
    exit(1);
  }

  // Declarations
  string in_file = argv[1];
  ifstream insrtuct_file(in_file);
  int intermed_counter = 1;


  // Check if the file can be read and initialised into a stream.
  // If file reading is not possible, program exits.
  if (insrtuct_file.fail()){
    cout << "Error! No file with instructions found. \n";
    cout << "Shutting down...\n";

    exit(2);
  };


  // Read and execute memory instructions from the file.
  string curr_line;
  string delimiter = ";";
  int curr_inst = 1;
  

  // First line must be max size of "bytes" in memory first.
  // Following lines -read all args for each line in the file.
  // All args semi-colon separated.
  //
  // First line:
  getline(insrtuct_file, curr_line);

  // Declare memories with different strategies
  vector<FauxMemory*> memories;
  memories.push_back(new FitFirstMemory(stoi(curr_line)));
  memories.push_back(new BestFitMemory(stoi(curr_line)));
  memories.push_back(new WorstFitMemory(stoi(curr_line)));
  


  // These are the instructions that are given to the memory.
  // Please note, it is assumed that instructions are given in a correct format.
  // No error checking for the file.
  //
  // Other lines:
  while(getline(insrtuct_file, curr_line)){
    vector<string> inst = extractInst(curr_line, delimiter);

    // Select action based on first arg (args[0]):
    //Allocate
    if(inst[0].compare("A") == 0){
      for(auto memory : memories){
        // Check that no parsing gremlins
        if(parsingHasIssues(inst[2])){
          cout << "Allocation error has occured!\n";
          memory->addAllocError(curr_inst);
        }
        else if(!memory->allocMem(new ProgramBlock(stoi(inst[1]), stoi(inst[2])))) {
          cout << "Allocation error has occured!\n";
          memory->addAllocError(curr_inst);
        };
      };
    
    
    //Deallocate
    }else if (inst[0].compare("D") == 0){
      for(auto memory : memories){
        if(parsingHasIssues(inst[1])){
          cout << "Deallocation error has occured!\n";
          memory->addDallocError(curr_inst, stoi(inst[1]));
        }
        else if(!memory->deallocMem(stoi(inst[1]))) {
          cout << "Deallocation error has occured!\n";
          memory->addDallocError(curr_inst, stoi(inst[1]));
        };
      };


    // Compact
    }else if (inst[0].compare("C") == 0){
      for(auto memory : memories){
        memory->compactMem();
      };


    // Output status
    }else if (inst[0].compare("O") == 0){
      // Open output file with specified name
      string out_file_s = in_file;
      size_t end = out_file_s.find(".");
      out_file_s = out_file_s.substr(0, end) + ".out" + to_string(intermed_counter);
      ofstream out_file(out_file_s);

      // Write to file
      for(auto memory : memories){
        makeSnapshot(memory, &out_file, memory->getStrategy());
        out_file << "\n";
      };
      intermed_counter ++;
      out_file.close();
    };

    // Increment instruction counter for the next cycle.
    curr_inst++;
  };


  // Output final state of memories to a '.out' file
  string out_file_s = in_file;
  size_t end = out_file_s.find(".");
  out_file_s = out_file_s.substr(0, end) + ".out";
  ofstream out_file(out_file_s);

  for(auto memory : memories){
    makeSnapshot(memory, &out_file, memory->getStrategy());
    out_file << "\n";
  };


  // Tidy up before finishing execution.
  out_file.close();
  insrtuct_file.close();
  return 0;
};