bgneal@0: // Copyright (C) 2012 by Brian Neal. bgneal@0: // This file is part of Cpp-Enigma, the Enigma Machine simulation. bgneal@0: // Cpp-Enigma is released under the MIT License (see License.txt). bgneal@0: // bgneal@0: // rotor.cpp - Implementation file for the rotor class. bgneal@0: bgneal@0: #include bgneal@0: #include bgneal@0: #include bgneal@0: #include "rotor.h" bgneal@0: bgneal@0: using namespace enigma; bgneal@0: bgneal@0: namespace bgneal@0: { bgneal@0: const char* const ucase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; bgneal@0: const std::set ucase_set(ucase, ucase + 26); bgneal@0: } bgneal@0: bgneal@0: rotor::rotor(const char* name, const char* wiring, int ring_setting, const char* stepping) bgneal@0: : rotor_name(name), bgneal@0: wiring_str(wiring), bgneal@0: ring_setting(ring_setting), bgneal@0: pos(0), bgneal@0: rotations(0) bgneal@0: { bgneal@0: // check wiring length bgneal@0: if (wiring_str.size() != 26) bgneal@0: { bgneal@0: throw rotor_error("invalid wiring length"); bgneal@0: } bgneal@0: bgneal@0: // ensure wiring contains only uppercase letters & every char must appear bgneal@0: // exactly once: bgneal@0: bgneal@0: std::array letter_counts {{ 0 }}; bgneal@0: for (int i = 0; i < 26; ++i) bgneal@0: { bgneal@0: const char c(wiring_str[i]); bgneal@0: bgneal@0: if (ucase_set.find(c) == ucase_set.end()) bgneal@0: { bgneal@0: throw rotor_error("invalid wiring"); bgneal@0: } bgneal@0: ++letter_counts[c - 'A']; bgneal@0: } bgneal@0: bgneal@0: if (std::find_if(letter_counts.begin(), bgneal@0: letter_counts.end(), bgneal@0: [](int n) { return n != 1; }) != letter_counts.end()) bgneal@0: { bgneal@0: throw rotor_error("invalid wiring; duplicate letter"); bgneal@0: } bgneal@0: }