diff --git a/helperFunctions.hpp b/helperFunctions.hpp index f0a9f16..64fdfc4 100644 --- a/helperFunctions.hpp +++ b/helperFunctions.hpp @@ -35,6 +35,7 @@ #include #include #include +#include enum CipherFlagLocation { CAESAR, PLAYFAIR, VIGENERE, ATBASH, MORSE, AUTOKEY, NUM_CIPHERS, @@ -43,10 +44,102 @@ std::string flagStrings[SIZE]; //Error handling bool failFlag = false; //Set if something fails -//For the getCipher function +//Sets a typedef for the functions for the return typedef std::string (*Fn)(std::ifstream&, bool); +/** + * @brief Set the array of strings that controls what each flag should look + * + */ +void setFlagStrings(){ + flagStrings[CAESAR] = "c"; + flagStrings[PLAYFAIR] = "p"; + flagStrings[VIGENERE] = "v"; + flagStrings[ATBASH] = "a"; + flagStrings[MORSE] = "m"; + flagStrings[AUTOKEY] = "u"; + flagStrings[CipherFlagLocation::ENCODE] = "e"; + flagStrings[CipherFlagLocation::DECODE] = "d"; + flagStrings[INPUT_FILE] = "i"; + flagStrings[OUTPUT_FILE] = "o"; +} + +/** + * @brief Takes the char** flags and turns them into a std::string to make it easier to process and sets the file names if necessary + * + * @param argc The number of arguments given + * @param argv The arguments given + * @param inputFileName The name of the input file if needed + * @param outputFileName The name of the output file if needed + */ +std::vector flagsToStrings(int argc, char** argv, std::string& inputFileName, std::string& outputFileName){ + std::vector args; + bool getInputFile = false; + bool getOutputFile = false; + //Step through every element in argv adding it to the string (without the dashes) + for(int cnt = 1;cnt < argc;++cnt){ + std::string tempArg = argv[cnt]; + //If you find a dash add the next character to the + if(tempArg.at(0) == '-'){ + //Step through every element in the rest of that string, adding all characters to the args string + for(unsigned long argCnt = 1;argCnt < tempArg.size();++argCnt){ + args.push_back(""); + args.at(args.size() - 1) = tempArg.at(argCnt); + //If one of the arguments is a file indicator set a flag to look for the file name + if(args.at(args.size() - 1) == flagStrings[INPUT_FILE]){ + getInputFile = true; + } + else if(args.at(args.size() - 1) == flagStrings[OUTPUT_FILE]){ + getOutputFile = true; + } + } + //Get the input file name if necessary + if(getInputFile){ + ++cnt; + if(cnt < argc){ + inputFileName = argv[cnt]; + } + else{ + ///Throw an error + } + } + //Get the output file name if necessary + if(getOutputFile){ + ++cnt; + if(cnt < argc){ + outputFileName = argv[cnt]; + } + else{ + ///Throw an error + } + } + } + else{ + //Throw an error + } + } + //Return the vector of strings + return args; +} + +/** + * @brief Takes an argument, searches the valid arguments that could be passed into the program, and sets the appropriate flags + * + * @param arg The argument that is currently being checked + * @param cipherFlags The array of booleans that act as flags that the rest of the program checks against + */ +void setArgs(std::string arg, bool cipherFlags[]){ + //Check against every flag that can currently be set + for(int cnt = CipherFlagLocation::CAESAR;cnt < CipherFlagLocation::SIZE;++cnt){ + //If the flag matches set the appropriate boolean and exit the function + if(arg == flagStrings[cnt]){ + cipherFlags[cnt] = true; + return; + } + } + ///Throw an error if the current flag was not found +} /** * @brief Takes all of the arguments that were given to the program and sets boolean flags inside the program that will change behavior @@ -57,37 +150,15 @@ typedef std::string (*Fn)(std::ifstream&, bool); * @param inputFileString The name of the input file, if given * @param outputFileString The name of the output file if given */ -void getFlags(int argc, char** argv, bool cipherFlags[], std::string& inputFileString, std::string& outputFileString){ - //Cycle through every argument - bool valid = false; - for(int cnt = 1;cnt < argc;++cnt){ - //Step through every element in the flagStrings and compare the flags. If the flags do not match or you go out of bounds in argv throw an error - for(int stringcnt = 0;stringcnt < SIZE;++stringcnt){ - if(argv[cnt] == flagStrings[stringcnt]){ - valid = cipherFlags[stringcnt] = true; - //If the flag showed an input file get the file name if possible - if(stringcnt == INPUT_FILE){ - //Make sure there is enough room in argv for the file name - if((cnt + 1) < argc){ - inputFileString = argv[++cnt]; - } - } - //If the flag showed an output file get the file name if possible - else if(stringcnt == OUTPUT_FILE){ - //Make sure there is enough room in argv for the file name - if((cnt + 1) < argc){ - outputFileString = argv[++cnt]; - } - } - break; - } - } - //If the flag was not valid throw an error - if(!valid){ - std::cout << argv[cnt] << " is an invalid flag" << std::endl; - return; - } - valid = false; +void getFlags(int argc, char** argv, bool cipherFlags[], std::string& inputString, std::string& outputString){ + //Set the strings that control each + setFlagStrings(); + //Turn the char** to string array + std::vector args = flagsToStrings(argc, argv, inputString, outputString); + //Cycle through every argument, checking it's validity and setting the correct flags + for(unsigned long argCnt = 0;argCnt < args.size();++argCnt){ + //Set all the arguments. If there is an invalid argument the function will throw an error + setArgs(args.at(argCnt), cipherFlags); } } @@ -102,7 +173,7 @@ bool checkFlags(bool flags[]){ int counter = 0; bool correct = false; //Run through each flag and counter how many are true - for(int cnt = 0;cnt < NUM_CIPHERS;++cnt){ + for(int cnt = CAESAR;cnt < NUM_CIPHERS;++cnt){ if(flags[cnt]){ ++counter; } @@ -114,30 +185,13 @@ bool checkFlags(bool flags[]){ } //Check if either encode or decode is set, but not both - if((flags[ENCODE] && flags[DECODE]) || (!flags[ENCODE] && !flags[DECODE])){ + if((flags[CipherFlagLocation::ENCODE] && flags[CipherFlagLocation::DECODE]) || (!flags[CipherFlagLocation::ENCODE] && !flags[CipherFlagLocation::DECODE])){ correct = false; } return correct; } -/** - * @brief Set the array of strings that controls what each flag should look - * - */ -void setFlagStrings(){ - flagStrings[CAESAR] = "-c"; - flagStrings[PLAYFAIR] = "-p"; - flagStrings[VIGENERE] = "-v"; - flagStrings[ATBASH] = "-a"; - flagStrings[MORSE] = "-m"; - flagStrings[AUTOKEY] = "-u"; - flagStrings[ENCODE] = "-e"; - flagStrings[DECODE] = "-d"; - flagStrings[INPUT_FILE] = "-i"; - flagStrings[OUTPUT_FILE] = "-o"; -} - /** * @brief Run the appropriate commands to use a Caesar cipher *