|
| 1 | +/* Exercise 25.1 */ |
| 2 | + |
| 3 | +#include<iostream> |
| 4 | +#include<sstream> |
| 5 | +#include<fstream> |
| 6 | +#include<iomanip> |
| 7 | +#include<vector> |
| 8 | +#include<bitset> |
| 9 | +#include"C25_Exercise_25.1.h" |
| 10 | + |
| 11 | +using namespace std; |
| 12 | + |
| 13 | +inline void error(string s) { throw runtime_error(s); } |
| 14 | +inline void error(const string& s, const string& s2) { error(s + s2); } |
| 15 | +inline void error(const string& s, int i) { ostringstream os; os << s << ": " << i; error(os.str()); } |
| 16 | +inline void keep_window_open() { char ch; cin >> ch; } |
| 17 | +inline int randint(int max) { return rand() % max; } |
| 18 | +inline int randint(int min, int max) { return randint(max - min) + min; } |
| 19 | + |
| 20 | +int main() |
| 21 | +{ |
| 22 | + enum Action { |
| 23 | + EXIT = -1, PRINTACTIONLIST, |
| 24 | + CASE1, CASE2, CASE3, CASE4, CASE5, CASE6, CASE7, CASE8, CASE9, CASE10 |
| 25 | + }; |
| 26 | + const string actionList = "\tList of actions:\n" |
| 27 | + " (1) Memory fragmentation, (2) Bits, (3) Infinite loop, (4) si = 128\n" |
| 28 | + " (5) Encrypt(), (6) Decrypt()\n" |
| 29 | + " (-1) Exit, (0) Print the list of actions\n"; |
| 30 | + cout << actionList; |
| 31 | + int action; |
| 32 | + bool cond{ true }; |
| 33 | + while (cond) try { |
| 34 | + cout << "\nPlease enter the action: "; |
| 35 | + if (!(cin >> action)) { ClearInput(cin); error("Error. Incorrect input"); } |
| 36 | + char ch; |
| 37 | + cin.get(ch); |
| 38 | + switch (action) { |
| 39 | + case CASE1: { |
| 40 | + cout << endl; |
| 41 | + cout << sp_2 << "sizeof(Message) = " << sizeof(Message) << " bytes" << endl; |
| 42 | + cout << sp_2 << "sizeof(Node) = " << sizeof(Node) << " bytes" << endl; |
| 43 | + cout << endl; |
| 44 | + |
| 45 | + constexpr int n = 10; |
| 46 | + vector<int> randoms; |
| 47 | + for (int i = 0; i < n * 2; ++i) { |
| 48 | + randoms.push_back(randint(n)); |
| 49 | + } |
| 50 | + int i = 0; |
| 51 | + while (i < n) { |
| 52 | + cout << sp_4 << right << setw(4) << i + 1 << ") "; |
| 53 | + Message* p1 = new Message{ randoms[i], randoms[i], randoms[i] }; |
| 54 | + p1->id += randoms[i * 2]; |
| 55 | + cout << "p1->" << p1 << ", "; |
| 56 | + Node* n1 = new Node(p1->id, p1->id); |
| 57 | + n1->id += p1->id; |
| 58 | + cout << "n1->" << n1 << ", "; |
| 59 | + delete p1; |
| 60 | + Node* n2 = new Node(n1->id, n1->id); |
| 61 | + n2->id += n1->id; |
| 62 | + cout << "n2->" << n2 << endl; |
| 63 | + i++; |
| 64 | + } |
| 65 | + cout << vsp_4; |
| 66 | + |
| 67 | + i = 0; |
| 68 | + while (i < n) { |
| 69 | + cout << sp_4 << right << setw(4) << i + 1 << ") "; |
| 70 | + Node* n1 = new Node(randoms[i], randoms[i]); |
| 71 | + n1->id += n1->id; |
| 72 | + cout << "n1->" << n1 << ", "; |
| 73 | + Node* n2 = new Node(n1->id, n1->id); |
| 74 | + n2->id += n1->id; |
| 75 | + cout << "n2->" << n2 << ", "; |
| 76 | + Message* p1 = new Message{ n2->id, n2->id, n2->id }; |
| 77 | + p1->id += n2->id; |
| 78 | + cout << "p1->" << p1 << endl; |
| 79 | + delete p1; |
| 80 | + i++; |
| 81 | + } |
| 82 | + |
| 83 | + cout << vsp_2 << "This example does not work correctly. " |
| 84 | + "This is probably caused by compiler optimization." << endl; |
| 85 | + |
| 86 | + cout << vsp_2; |
| 87 | + break; |
| 88 | + } |
| 89 | + case CASE2: { |
| 90 | + cout << endl; |
| 91 | + for (unsigned int i; cin >> i; ) { |
| 92 | + cout << dec << i << " == " |
| 93 | + << hex << "0x" << i << " == " |
| 94 | + << bitset<8 * sizeof(int)>{i} << '\n'; |
| 95 | + } |
| 96 | + |
| 97 | + |
| 98 | + cout << vsp_2; |
| 99 | + break; |
| 100 | + } |
| 101 | + case CASE3: { |
| 102 | + cout << endl; |
| 103 | + unsigned char max = 160; // very large |
| 104 | + for (signed char i = 0; i < max; ++i) cout << int(i) << '\n'; |
| 105 | + |
| 106 | + cout << vsp_2; |
| 107 | + break; |
| 108 | + } |
| 109 | + case CASE4: { |
| 110 | + cout << endl; |
| 111 | + int si = 128; |
| 112 | + unsigned int ui = si; |
| 113 | + cout << dec << si << " == " |
| 114 | + << hex << "0x" << si << " == " |
| 115 | + << bitset<8 * sizeof(int)>{ui} << '\n'; |
| 116 | + |
| 117 | + cout << vsp_2; |
| 118 | + break; |
| 119 | + } |
| 120 | + case CASE5: { |
| 121 | + cout << endl; |
| 122 | + Encrypt(); |
| 123 | + cout << vsp_2; |
| 124 | + break; |
| 125 | + } |
| 126 | + case CASE6: { |
| 127 | + cout << endl; |
| 128 | + Decrypt(); |
| 129 | + cout << vsp_2; |
| 130 | + break; |
| 131 | + } |
| 132 | + case PRINTACTIONLIST: |
| 133 | + cout << actionList; |
| 134 | + break; |
| 135 | + case EXIT: |
| 136 | + cond = false; |
| 137 | + break; |
| 138 | + default: |
| 139 | + error("Error. Incorrect action number"); |
| 140 | + break; |
| 141 | + } |
| 142 | + } |
| 143 | + catch (runtime_error& e) { |
| 144 | + cerr << e.what() << endl; |
| 145 | + } |
| 146 | + catch (...) { |
| 147 | + cerr << "Error. Exception\n"; |
| 148 | + return 1; |
| 149 | + } |
| 150 | + return 0; |
| 151 | +} |
| 152 | + |
| 153 | +void ClearInput(istream& is) |
| 154 | +{ |
| 155 | + is.clear(); |
| 156 | + is.ignore(numeric_limits<streamsize>::max(), '\n'); |
| 157 | +} |
| 158 | + |
| 159 | +void Encrypt() |
| 160 | +{ |
| 161 | + const int nchar = 2 * sizeof(long); // 64 bits |
| 162 | + const int kchar = 2 * nchar; // 128 bits |
| 163 | + string op; |
| 164 | + string key; |
| 165 | + string infile; |
| 166 | + string outfile; |
| 167 | + cout << "please enter input file name, output file name, and key:\n"; |
| 168 | + cin >> infile >> outfile >> key; |
| 169 | + while (key.size() < kchar) key += '0'; // pad key |
| 170 | + ifstream inf(infile); |
| 171 | + ofstream outf(outfile); |
| 172 | + if (!inf || !outf) error("bad file name"); |
| 173 | + const unsigned long* k = reinterpret_cast<const unsigned long*>(key.data()); |
| 174 | + unsigned long outptr[2]; |
| 175 | + char inbuf[nchar]; |
| 176 | + unsigned long* inptr = reinterpret_cast<unsigned long*>(inbuf); |
| 177 | + int count = 0; |
| 178 | + while (inf.get(inbuf[count])) { |
| 179 | + outf << hex; // use hexadecimal output |
| 180 | + if (++count == nchar) { |
| 181 | + encipher(inptr, outptr, k); |
| 182 | + // pad with leading zeros: |
| 183 | + outf << setw(8) << setfill('0') << outptr[0] << ' ' |
| 184 | + << setw(8) << setfill('0') << outptr[1] << ' '; |
| 185 | + count = 0; |
| 186 | + } |
| 187 | + } |
| 188 | + if (count) { // pad |
| 189 | + while (count != nchar) inbuf[count++] = '0'; |
| 190 | + encipher(inptr, outptr, k); |
| 191 | + outf << outptr[0] << ' ' << outptr[1] << ' '; |
| 192 | + } |
| 193 | +} |
| 194 | + |
| 195 | +void Decrypt() |
| 196 | +{ |
| 197 | + const int nchar = 2 * sizeof(long); // 64 bits |
| 198 | + const int kchar = 2 * nchar; // 128 bits |
| 199 | + string op; |
| 200 | + string key; |
| 201 | + string infile; |
| 202 | + string outfile; |
| 203 | + cout << "please enter input file name, output file name, and key:\n"; |
| 204 | + cin >> infile >> outfile >> key; |
| 205 | + while (key.size() < kchar) key += '0'; // pad key |
| 206 | + ifstream inf(infile); |
| 207 | + ofstream outf(outfile); |
| 208 | + if (!inf || !outf) error("bad file name"); |
| 209 | + const unsigned long* k = reinterpret_cast<const unsigned long*>(key.data()); |
| 210 | + unsigned long inptr[2]; |
| 211 | + char outbuf[nchar + 1]; |
| 212 | + outbuf[nchar] = 0; // terminator |
| 213 | + unsigned long* outptr = reinterpret_cast<unsigned long*>(outbuf); |
| 214 | + inf.setf(ios_base::hex, ios_base::basefield); // use hexadecimal input |
| 215 | + while (inf >> inptr[0] >> inptr[1]) { |
| 216 | + decipher(inptr, outptr, k); |
| 217 | + outf << outbuf; |
| 218 | + } |
| 219 | +} |
| 220 | + |
| 221 | +void encipher( |
| 222 | + const unsigned long* const v, |
| 223 | + unsigned long* const w, |
| 224 | + const unsigned long* const k) |
| 225 | +{ |
| 226 | + static_assert(sizeof(long) == 4, "size of long wrong for TEA"); |
| 227 | + unsigned long y = v[0]; |
| 228 | + unsigned long z = v[1]; |
| 229 | + unsigned long sum = 0; |
| 230 | + const unsigned long delta = 0x9E3779B9; |
| 231 | + for (unsigned long n = 32; n-- > 0; ) { |
| 232 | + y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3]; |
| 233 | + sum += delta; |
| 234 | + z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3]; |
| 235 | + } |
| 236 | + w[0] = y; |
| 237 | + w[1] = z; |
| 238 | +} |
| 239 | + |
| 240 | +void decipher( |
| 241 | + const unsigned long* const v, |
| 242 | + unsigned long* const w, |
| 243 | + const unsigned long* const k) |
| 244 | +{ |
| 245 | + static_assert(sizeof(long) == 4, "size of long wrong for TEA"); |
| 246 | + unsigned long y = v[0]; |
| 247 | + unsigned long z = v[1]; |
| 248 | + unsigned long sum = 0xC6EF3720; |
| 249 | + const unsigned long delta = 0x9E3779B9; |
| 250 | + // sum = delta<<5, in general sum = delta * n |
| 251 | + for (unsigned long n = 32; n-- > 0; ) { |
| 252 | + z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3]; |
| 253 | + sum -= delta; |
| 254 | + y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3]; |
| 255 | + } |
| 256 | + w[0] = y; |
| 257 | + w[1] = z; |
| 258 | +} |
0 commit comments