CS480-Projects/Sim03/configops.c

608 lines
No EOL
21 KiB
C

#include "configops.h"
#include "StandardConstants.h"
#include "StringUtils.h"
/*
Name: clearConfigData
Process: frees dynamically allocated config data structure
if it has not already been freed
Function Input/Parameters: pointer to config data structure (ConfigDataType *)
Function Output/Parameters: none
Function Output/Returned: NULL (ConfigDataType *)
Device Input/Device: none
Device Output/Device: none
Dependencies: free
*/
ConfigDataType *clearConfigData(ConfigDataType *configData)
{
// initialize function and variables
// check that config data pointer is not null
if(configData != NULL)
{
// free data structure memory
// fct: free
free(configData);
// set config pointer to NULL
configData = NULL;
}
// set config data pointer to null
return NULL;
}
/*
Name: configCodeToString
Process: utility fct converts configuration code numbers to string they represent
Function Input/Parameters: configuration code (int)
Function Output/Parameters: resulting output string (char *)
Function Output/Returned: none
Device Input/Device: none
Device Output/Device: none
Dependencies: copyString
*/
void configCodeToString(int code, char *outString)
{
// define array with eight items, and short (10) lengths
char displayStrings[8][10] = {"SJF-N","SRTF-P","FCFS-P","RR-P",
"FCFS-N","Monitor", "File", "Both"};
// copy string to return parameter
// fct: copyString
copyString(outString, displayStrings[code]);
// void function, no return.
}
/*
Name: displayConfigData
Process: screen dump/display of all config data
Function Input/Parameters: pointer to config data structure (ConfigDataType *)
Function Output/Parameters: none
Function Output/Returned: none
Device Input/Device: none
Device Output/Monitor: displayed as spec'd
Dependencies: configCodeToString, printf
*/
void displayConfigData(ConfigDataType *configData)
{
// initialize function and variables
char displayString[STD_STR_LEN];
// print lines of display for all member values
// fct: printf, codeToString
printf("Config File Display\n");
printf("-------------------\n");
printf("Version : %3.2f\n", configData->version);
printf("Program File Name : %s\n", configData->metaDataFileName);
configCodeToString(configData->cpuSchedCode, displayString);
printf("CPU Schedule Selection: %s\n", displayString);
printf("Quantum Time : %d\n", configData->quantumCycles);
printf("Memory Display : ");
if(configData->memDisplay)
{
printf("On\n");
}
else
{
printf("Off\n");
}
printf("Memory Available : %d\n", configData->memAvailable);
printf("Process Cycle Rate : %d\n", configData->procCycleRate);
printf("I/O Cycle Rate : %d\n", configData->ioCycleRate);
configCodeToString(configData->logToCode, displayString);
printf("Log to Selection : %s\n", displayString);
printf("Log File Name : %s\n\n", configData->logToFileName);
// void function, no return.
}
/*
Name: getConfigData
Process: driver function for capturing config data from config file
Function Input/Parameters: file name (const char *)
Function Output/Parameters: pointer to config data pointer (ConfigDataType **)
end/result state message pointer (char *)
Function Output/Returned: Boolean result of data access operation (bool)
Device Input/File: config data uploaded
Device Output/Device: none
Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose,
malloc, free, stripTrailingSpaces, getDataLineCode, fscanf,
strToLowerCase, valueInRange, getCpuSchedCode, getLogToCode
*/
bool getConfigData(const char *fileName,
ConfigDataType **configData, char *endStateMsg)
{
// initialize function and variables
// set constant number of data lines
const int NUM_DATA_LINES = 10;
// set read only constant
const char READ_ONLY_FLAG[] = "r";
// create pointer for data input
ConfigDataType *tempData;
// declare other variables
FILE *fileAccessPtr;
char dataBuffer[MAX_STR_LEN], lowerCaseDataBuffer[MAX_STR_LEN];
int intData, dataLineCode, lineCtr = 0;
double doubleData;
// set endStateMsg to success
// fct: copyString
char testMsg[] = "Configuration file upload successful";
copyString(endStateMsg, testMsg);
// initialize config data pointer in case of return error
*configData = NULL;
// open file
// fct: fopen
fileAccessPtr = fopen(fileName, READ_ONLY_FLAG);
// check for file open failure
if(fileAccessPtr == NULL)
{
// set end state message to config file access error
// fct: copyString
char testMsg[] = "Configuration file access error";
copyString(endStateMsg, testMsg);
// return file access error
return false;
}
// get first line, check for failure
// fct: getStringToDelimiter, compareString
if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer)
|| compareString(dataBuffer, "Start Simulator Configuration File") != 0)
{
// close file access
// fct: fclose
fclose(fileAccessPtr);
// set end state message to corrupt leader line error
// fct: copyString
copyString(endStateMsg, "Corrupt configuration leader line error");
// return corrupt file data
return false;
}
// create temporary pointer to configuration data structure
// fct: malloc
tempData = (ConfigDataType *) malloc(sizeof(ConfigDataType));
// loop to end of config data items
while(lineCtr < NUM_DATA_LINES)
{
// get line leader, check for failure
// fct: getStringToDelimiter
if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer))
{
// free temp struct memory
// fct: free
free(tempData);
// close file access
// fct: fclose
fclose(fileAccessPtr);
// set end state message to line capture failure
// fct: copyString
copyString(endStateMsg,
"Configuration data leader line capture error");
// return incomplete file error
return false;
}
// strip trailing spaces of config leader lines
// for use in other fcts
// fct: stripTrailingSpaces
stripTrailingSpaces(dataBuffer);
// find correct data line code number from string
// fct: getDataLineCode
dataLineCode = getDataLineCode(dataBuffer);
// check for data line found
if(dataLineCode != CFG_CORRUPT_PROMPT_ERR)
{
// get data value
// check for version number (double value)
if(dataLineCode == CFG_VERSION_CODE)
{
// get version number
// fct: fscanf
fscanf(fileAccessPtr, "%lf", &doubleData);
}
// otherwise, check for metaData, fileNames,
// CPU Scheduling names, or memory display setting (strings)
else if(dataLineCode == CFG_MD_FILE_NAME_CODE ||
dataLineCode == CFG_LOG_FILE_NAME_CODE ||
dataLineCode == CFG_CPU_SCHED_CODE ||
dataLineCode == CFG_LOG_TO_CODE ||
dataLineCode == CFG_MEM_DISPLAY_CODE)
{
// get string input
// fct: fscanf
fscanf(fileAccessPtr, "%s", dataBuffer);
// set string to lower case for testing in valueInRange
// fct: strToLowerCase
strToLowerCase(lowerCaseDataBuffer, dataBuffer);
}
// otherwise, assume integer data
else
{
// get integer input
// fct: fscanf
fscanf(fileAccessPtr, "%d", &intData);
}
// check for data value in range
// fct: valueInRange
if(valueInRange(dataLineCode, intData,
doubleData, lowerCaseDataBuffer))
{
// assign to data pointer depending on config item
// (all config line possibilities)
// fct: copyString, getCpuSchedCode,
// compareString, getLogToCode, as needed
switch(dataLineCode)
{
case CFG_VERSION_CODE:
tempData->version = doubleData;
break;
case CFG_MD_FILE_NAME_CODE:
copyString(tempData->metaDataFileName, dataBuffer);
break;
case CFG_CPU_SCHED_CODE:
tempData->cpuSchedCode =
getCpuSchedCode(lowerCaseDataBuffer);
break;
case CFG_QUANT_CYCLES_CODE:
tempData->quantumCycles = intData;
break;
case CFG_MEM_DISPLAY_CODE:
tempData->memDisplay =
compareString(lowerCaseDataBuffer, "on") == 0;
break;
case CFG_MEM_AVAILABLE_CODE:
tempData->memAvailable = intData;
break;
case CFG_PROC_CYCLES_CODE:
tempData->procCycleRate = intData;
break;
case CFG_IO_CYCLES_CODE:
tempData->ioCycleRate = intData;
break;
case CFG_LOG_TO_CODE:
tempData->logToCode = getLogToCode(lowerCaseDataBuffer);
break;
case CFG_LOG_FILE_NAME_CODE:
copyString(tempData->logToFileName, dataBuffer);
break;
}
}
// otherwise, assume data value not in range
else
{
// free temp struct memory
// fct: free
free(tempData);
// close file access
// fct: fclose
fclose(fileAccessPtr);
// set end state message to configuration data out of range
// fct: copyString
copyString(endStateMsg, "Configuration item out of range");
// return data out of range
return false;
}
}
// otherwise, check for data line not found
else
{
// free temp struct memory
// fct: free
free(tempData);
// close file access
// fct: fclose
fclose(fileAccessPtr);
// set end state message to configuration corrupt prompt error
// fct: copyString
copyString(endStateMsg, "Corrupted configuration prompt");
// return corrupt config file code
return false;
}
// increment line counter
lineCtr = lineCtr + 1;
}
// end loop to end of config data items
// acquire end of sim config string
// fct: getStringToDelimiter, compareString
if(!getStringToDelimiter(fileAccessPtr, PERIOD, dataBuffer) ||
compareString(dataBuffer, "End Simulator Configuration File") != 0)
{
// free temp struct memory
// fct: free
free(tempData);
// close file access
// fct: fclose
fclose(fileAccessPtr);
// set end state message to corrupt configuration end line
// fct: copyString
copyString(endStateMsg, "Configuration end line capture error");
// return corrupt file data
return false;
}
// test for "file only" output so memory diagnostics do not display
tempData->memDisplay = tempData->memDisplay &&
tempData->logToCode != LOGTO_FILE_CODE;
// assign temp ptr to parameter return ptr
*configData = tempData;
// close file access
// fct: fclose
fclose(fileAccessPtr);
// return no error code
return true;
}
/*
Name: getCpuSchedCode
Process: converts cpu schedule string to code (all scheduling possibilities)
Function Input/Parameters: lower case code string (const char *)
Function Output/Parameters: none
Function Output/Returned: cpu schedule code (ConfigDataCodes)
Device Input/Device: none
Device Output/Device: none
Dependencies: compareString
*/
ConfigDataCodes getCpuSchedCode(const char *lowerCaseCodeStr)
{
// iniitalize function and variables
// set default return to FCFS-N
ConfigDataCodes returnVal = CPU_SCHED_FCFS_N_CODE;
// check for SJF-N
// fct: compareString
if(compareString(lowerCaseCodeStr, "sjf-n") == 0)
{
// set SJF-N code
returnVal = CPU_SCHED_SJF_N_CODE;
}
// check for SRTF-P
// fct: compareString
if(compareString(lowerCaseCodeStr, "srtf-p") == 0)
{
// set SRTF-P code
returnVal = CPU_SCHED_SRTF_P_CODE;
}
// check for FCFS-P
// fct: compareString
if(compareString(lowerCaseCodeStr, "fcfs-p") == 0)
{
// set FCFS-P code
returnVal = CPU_SCHED_FCFS_P_CODE;
}
// check for RR-P
// fct: compareString
if(compareString(lowerCaseCodeStr, "rr-p") == 0)
{
// set RR-P code
returnVal = CPU_SCHED_RR_P_CODE;
}
return returnVal;
}
/*
Name: getDataLineCode
Process: converts leader line string to configuration code value
(processes all config file leader lines)
Function Input/Parameters: config leader line string (const char *)
Function Output/Parameters: none
Function Output/Returned: configuration code value (ConfigCodeMessages)
Device Input/Device: none
Device Output/Device: none
Dependencies: compareString
*/
ConfigCodeMessages getDataLineCode(const char *dataBuffer)
{
// iniitalize function and variables
// return appropriate code depending on prompt string provided
// fct: compareString
if(compareString(dataBuffer, "Version/Phase") == 0)
{
return CFG_VERSION_CODE;
}
if(compareString(dataBuffer, "File Path") == 0)
{
return CFG_MD_FILE_NAME_CODE;
}
if(compareString(dataBuffer, "CPU Scheduling Code") == 0)
{
return CFG_CPU_SCHED_CODE;
}
if(compareString(dataBuffer, "Quantum Time (cycles)") == 0)
{
return CFG_QUANT_CYCLES_CODE;
}
if(compareString(dataBuffer, "Memory Display (On/Off)") == 0)
{
return CFG_MEM_DISPLAY_CODE;
}
if(compareString(dataBuffer, "Memory Available (KB)") == 0)
{
return CFG_MEM_AVAILABLE_CODE;
}
if(compareString(dataBuffer, "Processor Cycle Time (msec)") == 0)
{
return CFG_PROC_CYCLES_CODE;
}
if(compareString(dataBuffer, "I/O Cycle Time (msec)") == 0)
{
return CFG_IO_CYCLES_CODE;
}
if(compareString(dataBuffer, "Log To") == 0)
{
return CFG_LOG_TO_CODE;
}
if(compareString(dataBuffer, "Log File Path") == 0)
{
return CFG_LOG_FILE_NAME_CODE;
}
// return corrupt leader line error code
return CFG_CORRUPT_PROMPT_ERR;
}
/*
Name: getLogToCode
Process: converts "log to" text to
configuration data code (three log to strings)
Function Input/Parameters: lower case log to string (const char *)
Function Output/Parameters: none
Function Output/Returned: configuration data code value
Device Input/Device: none
Device Output/Device: none
Dependencies: compareString
*/
ConfigDataCodes getLogToCode(const char *lowerCaseLogToStr)
{
// initialize function and variables
// set default to log to monitor
ConfigDataCodes returnVal = LOGTO_MONITOR_CODE;
// check for BOTH
// fct: compareString
if(compareString(lowerCaseLogToStr, "both") == 0)
{
// set return value to both code
returnVal = LOGTO_BOTH_CODE;
}
// check for FILE
// fct: compareString
if(compareString(lowerCaseLogToStr, "file") == 0)
{
// set return value to file code
returnVal = LOGTO_FILE_CODE;
}
// return selected code
return returnVal;
}
/*
Name: stripTrailingSpaces
Process: removes trailing spaces from input config leader lines
Function Input/Parameters: config leader line string (char *)
Function Output/Parameters: updates config leader line string (char *)
Function Output/Returned: none
Device Input/Device: none
Device Output/Device: none
Dependencies: getStringLength
*/
void stripTrailingSpaces(char *str)
{
// initialize index to length of string - 1 to get highest array index
int index = getStringLength(str) - 1;
// loop while space is found at the end of string
while(str[index] == SPACE)
{
// set element to NULL_CHAR
str[index] = NULL_CHAR;
// decrement index
index = index - 1;
}
// end loop from end of string
// void function, no return.
}
/*
Name: valueInRange
Process: checks for config data values in range, including str values
Function Input/Parameters: line code number for specific config value (int),
integer value, as needed (int),
double value, as needed (double),
string value, as needed (const char *)
Function Output/Parameters: none
Function Output/Returned: Boolean result of the range test (bool)
Device Input/Device: none
Device Output/Device: none
Dependencies: compareString
*/
bool valueInRange(int lineCode, int intVal, double doubleVal,
const char *lowerCaseStringVal)
{
// initialize function and variables
// set result to true, all tests are to find false
bool result = true;
// use line code to identify prompt line
switch(lineCode)
{
// for version code
case CFG_VERSION_CODE:
// check if limits of version code are exceeded
if(doubleVal < 0.00 || doubleVal > 10.00)
{
// set bool to false
result = false;
}
// break
break;
// for cpu scheduling code
case CFG_CPU_SCHED_CODE:
// check for not finding one of the scheduling strings
// fct: compareString
if(compareString(lowerCaseStringVal, "fcfs-n") != 0 &&
compareString(lowerCaseStringVal, "sjf-n") != 0 &&
compareString(lowerCaseStringVal, "srtf-p") != 0 &&
compareString(lowerCaseStringVal, "fcfs-p") != 0 &&
compareString(lowerCaseStringVal, "rr-p") != 0)
{
// set bool to false
result = false;
}
// break
break;
// for quantum cycles
case CFG_QUANT_CYCLES_CODE:
// check for quantum cycles limits exceeded
if(intVal < 0 || intVal > 100)
{
// set bool to false
result = false;
}
// break
break;
// for memory display
case CFG_MEM_DISPLAY_CODE:
// check for not finding either on or off
// fct: compareString
if(compareString(lowerCaseStringVal, "on") != 0 &&
compareString(lowerCaseStringVal, "off") != 0)
{
// set bool to false
result = false;
}
// break
break;
// for memory available
case CFG_MEM_AVAILABLE_CODE:
// check for memory limits exceeded
if(intVal < 1024 || intVal > 102400)
{
// set bool to false
result = false;
}
// break
break;
// check for process cycles
case CFG_PROC_CYCLES_CODE:
// check for process cycles limits exceeded
if(intVal < 1 || intVal > 100)
{
// set bool to false
result = false;
}
// break
break;
// check for process cycles
case CFG_IO_CYCLES_CODE:
// check for process cycles limits exceeded
if(intVal < 1 || intVal > 1000)
{
// set bool to false
result = false;
}
// break
break;
// check for log to operation
case CFG_LOG_TO_CODE:
// check for not finding one of the log to strings
// fct: compareString
if(compareString(lowerCaseStringVal, "both") != 0 &&
compareString(lowerCaseStringVal, "monitor") != 0 &&
compareString(lowerCaseStringVal, "file") != 0)
{
// set bool to false
result = false;
}
// break
break;
}
// return result of limits analysis
return result;
}