//Ciphers/SourceFiles/Vigenere.cpp //Matthew Ellison // Created: 4-29-18 //Modified: 5-16-18 //This file contains the implementation of the Vigenere class #include "../Headers/Vigenere.hpp" #include #include #include /** * @brief The current library's version number * */ const std::string Vigenere::version = "1.0"; /** * @brief Construct a new Vigenere object * */ Vigenere::Vigenere(){ reset(); } /** * @brief Destroy the Vigenere object * */ Vigenere::~Vigenere(){ } /** * @brief Removes all invalid characters from input and sets it to inputString * * @param input The string you want to encode/decode */ void Vigenere::setInputString(std::string input){ //Loop through every character in input. Remove all whitespace and punctuation and make sure all letters are capital and add it to inputString for(unsigned int cnt = 0;cnt < input.size();++cnt){ char letter = input[cnt]; if(isupper(letter)){ inputString += letter; } else if(islower(letter)){ inputString += toupper(letter); } //If the letter is whitespace or punctuation do nothing } } /** * @brief Returns the string you wish to encode/decode * * @return The string you wish to encode/decode */ std::string Vigenere::getInputString() const{ return inputString; } /** * @brief Returns the encoded/decoded message * * @return The encoded/decoded message */ std::string Vigenere::getOutputString() const{ return outputString; } /** * @brief Removes all invalid characters from key and sets it to keyword * * @param key The keyword used for the cipher */ void Vigenere::setKeyword(std::string key){ //Loop through every letter in the key and make sure all of them are uppercase letters for(unsigned int cnt = 0;cnt < key.size();++cnt){ char letter = key[cnt]; if(isupper(letter)){ keyword += letter; } else if(islower(letter)){ keyword += toupper(letter); } //If it is not a letter ignore it } //Make sure offset is empty before adding to it offset.clear(); setOffset(); } /** * @brief Returns the keyword you are using for the cipher * * @return The keyword you are using for the cipher */ std::string Vigenere::getKeyword() const{ return keyword; } /** * @brief Uses keyword to set the offsets of the letters used during encoding/decoding * */ void Vigenere::setOffset(){ //Reserve the correct size to increase speed later offset.reserve(keyword.size()); //Loop through every letter in keyword and get the offset from A for(char letter : keyword){ offset.push_back((letter - 'A') % 26); } } /** * @brief Returns the vector that holds the offsets of the letters used during encoding/decoding * * @return A the vector holding offsets of the letters used during encoding/decoding * @note Used mostly for debuging */ std::vector Vigenere::getOffsets() const{ return offset; } /** * @brief Encodes the inputString using the Vigenere cipher and saves the result in outputString * * @return The encoded message */ std::string Vigenere::encode(){ //Reserve the correct size for the output string to increase speed for longer messages outputString.reserve(inputString.size()); //Step through every charater in the inputString and advance it the correct amount, according to offset for(unsigned int cnt = 0;cnt < inputString.size();++cnt){ char letter = (inputString[cnt] + offset[cnt % offset.size()]); //By using % you allow it to loop without having a separate counter //Make sure the character is still a letter, if not, wrap around if(letter < 'A'){ letter += 26; } else if(letter > 'Z'){ letter -= 26; } outputString += letter; } return outputString; } /** * @brief Sets all of the variables for the cipher and returns the result * * @param key The keyword used in the cipher * @param input The message that you wish to encode * @return The encoded message */ std::string Vigenere::encode(std::string key, std::string input){ reset(); setKeyword(key); //Throw an error if there is no keyword //Would be better to throw an error here if(keyword == ""){ return "Error! Empty keyword\n"; } setInputString(input); return encode(); } /** * @brief Decodes the inputString using the Vigenere cipher and saves the result in outputString * * @return The decoded message */ std::string Vigenere::decode(){ //Reserve the correct size for the output string to increase speed for longer messages outputString.reserve(inputString.size()); //Step through every charater in the inputString and reduce it the correct amount, according to offset for(unsigned int cnt = 0;cnt < inputString.size();++cnt){ char letter = (inputString[cnt] - offset[cnt % offset.size()]); //By using % you allow it to loop without having a separate counter if(letter < 'A'){ letter += 26; } else if(letter > 'Z'){ letter -= 26; } outputString += letter; } return outputString; } /** * @brief Sets all of the variables for the cipher and returns the result * * @param key The keyword used in the cipher * @param input The message that you wish to decode * @return The decoded message */ std::string Vigenere::decode(std::string key, std::string input){ reset(); setKeyword(key); //Throw an error if there is no keyword //Would be better to throw an error here if(keyword == ""){ return "Error! Empty keyword\n"; } setInputString(input); return decode(); } /** * @brief Makes sure all of the variables are empty * */ void Vigenere::reset(){ inputString = outputString = keyword = ""; offset.clear(); } /** * @brief Returns a string containing the version information * * @return The version information */ std::string Vigenere::getVersion(){ return version; }