-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenigma.cpp
More file actions
172 lines (123 loc) · 5.4 KB
/
Copy pathenigma.cpp
File metadata and controls
172 lines (123 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include "rotor.h" // necessary as Rotor class is used as an arguement below
#include "reflector.h" // necessary as Reflector class is used as an argument below
#include "plugboard.h" // necessary as Plugboard class is used as an argument below
#include "enigma.h"
#include "errors.h"
// ========== internal helper functions ==========
// this function returns the index position of the second argument in the array
int search_array(const int mapping[], const int value){
for ( int i = 0; i < NUM_OF_ALPHABETS; i++){
if ( mapping[i] == value ) return i;
}
// return -1 if not found
return -1;
}
// Checks extension of a filename. Returns true if it matches.
bool check_extension(int count, std::string extension, int position, char* argv[]){
int length = extension.length();
for (int i = 0; i < length; i++){
if(argv[position][count + i] != extension.at(i)) return false;
}
// extension matches. returns true.
return true;
}
// ========== functions that are not member of any user defined class ==========
// this function checks that the command line arguments are of the right format
void check_command_line(int argc, char* argv[]){
// check for at least 4 command line arguments
if ( argc < FIXED_ARGV ) {
std::cerr << "usage: enigma plugboard-file reflector-file (<rotor-file>)* rotor-positions" << std::endl;
throw INSUFFICIENT_NUMBER_OF_PARAMETERS;
}
// check that command line config files has the correct file extension
for ( int i = 1; i < argc; i++){
char dot = argv[i][0];
int count = 0;
bool check_arg = true;
// count number of chars until '.'
while ( dot != '.'){
dot = argv[i][count];
count++;
}
// check extension for pb
if(i==1) check_arg = check_extension(count, "pb", i, argv);
// check extension for rf
if(i==2) check_arg = check_extension(count, "rf", i, argv);
// check extension for rot
if(i > 2 && i < argc-1) check_arg = check_extension(count, "rot", i, argv);
// check extension for pos
if(i == argc-1) check_arg = check_extension(count, "pos", i, argv);
if ( check_arg == false) {
std::cerr << "usage: enigma plugboard-file reflector-file (<rotor-file>)* rotor-positions" << std::endl;
throw ERROR_OPENING_CONFIGURATION_FILE;
}
}
}
// ========== Enigma class member functions ==========
// Default constructor
Enigma::Enigma(int argc, char** argv)
: argc(argc), argv(argv), plugboard(Plugboard(argv[1])), reflector(Reflector(argv[2])), number_of_rotors(argc - FIXED_ARGV){
if ( number_of_rotors > 0) {
// Assign pointer to the array of rotors and check for insufficient memory
set_of_rotors = new (std::nothrow) Rotor[number_of_rotors];
if(set_of_rotors == nullptr){
std::cerr << "Insufficient memory to allocate array of rotors." << std::endl;
throw INSUFFICIENT_MEMORY;
}
// initialise each rotor in the array accordingly
initialise_enigma_rotors(set_of_rotors, number_of_rotors, argv);
} else set_of_rotors = nullptr;
}
// Destructor for Enigma to remove pointer of rotors when object is destroyed
Enigma::~Enigma(){
if ( number_of_rotors == 0) delete set_of_rotors;
else delete [] set_of_rotors;
}
// this function brings together all the necessary parts of the enigma machine to encode/decode input to output
void Enigma::decoder_encoder(const int input, const Plugboard plugboard, const Reflector reflector, Rotor* const set_of_rotors, const int number_of_rotors){
// initialise ouput as 0
int output = 0;
//Scramble through Plugboard
output = plugboard.right_to_left(input);
//Enter row of rotors from plugboard. Start from the right. Does not enter for loop if number_of_rotors = 0.
if ( number_of_rotors > 0 ){
for ( int i = number_of_rotors - 1; i >= 0; i--){
// if not the rightmost rotor, check notch of right rotor and turn if at 12 o'clock
(*(set_of_rotors + i)).rotor_rotation(set_of_rotors, number_of_rotors, i);
output = (set_of_rotors + i) -> right_to_left(output);
}
}
//Enter reflector
output = reflector.reflector_output(output);
//Enter set of rotors from reflector. Start from the left. Does not enter for loop if number_of_rotors = 0.
if ( number_of_rotors > 0 ){
for ( int i = 0; i < number_of_rotors ; i++){
output = (*(set_of_rotors + i)).left_to_right(output);
}
}
//Scramble through Plugboard
output = plugboard.left_to_right(output);
char letter = static_cast<char>(output + ASCII_OFFSET);
std::cout << letter;
}
// this function reads input from from the standard input stream into an array
void Enigma::encrypt(){
char character;
while ( std::cin >> std::ws >> character){
// to check if input is from A to Z
if( !isalpha(character) || !isupper(character) ){
std::cerr << character << " is not a valid input character (input characters must be upper case letters A-Z)!" << std::endl;
throw INVALID_INPUT_CHARACTER;
}
// convert string to integer if numeric and add to enigma_input
int input = static_cast<int>(character) - ASCII_OFFSET;
// decode/endocde input
decoder_encoder(input, plugboard, reflector, set_of_rotors, number_of_rotors);
// check if newline is reached in standard input stream
if (std::cin.peek() == '\n') break;
}
}