EnigmaMachineCore 0.1.0
A modular Enigma Machine simulation in C++20
Loading...
Searching...
No Matches
EnigmaConfigLoader.cpp
Go to the documentation of this file.
2#include <sstream>
3#include <stdexcept>
4#include <toml.hpp>
5#include "config.hpp"
6
7namespace {
8
21void validateTransformerConfig(const toml::value& data, const std::string& expectedType, const std::string& fileName) {
22 try {
23 auto size = toml::find<int>(data, "size");
24 if (size != TRANSFORMER_SIZE) {
25 throw std::runtime_error("Transformer size mismatch: expected " + std::to_string(TRANSFORMER_SIZE) +
26 ", got " + std::to_string(size));
27 }
28
29 auto typeStr = toml::find<std::string>(data, "type");
30 if (typeStr != expectedType) {
31 throw std::runtime_error("Wrong config file: expected " + expectedType + ", got " + typeStr);
32 }
33 } catch (const std::exception& e) {
34 throw std::runtime_error("Validation error in " + fileName + ": " + e.what());
35 }
36}
37} // namespace
38
40 std::istringstream stream(provider.loadAsset(fileName.string()));
41 auto rotorData = toml::parse(stream, fileName.string());
42 validateTransformerConfig(rotorData, "rotor", fileName.string());
43
44 RotorConfig rotorConfig;
45 rotorConfig.notchPosition = toml::find<AlphabetIndex>(rotorData, "rotor", "notchPosition");
46 rotorConfig.wiring = toml::find<std::array<AlphabetIndex, TRANSFORMER_SIZE>>(rotorData, "rotor", "forward");
47
48 return rotorConfig;
49}
50
52 std::istringstream stream(provider.loadAsset(fileName.string()));
53 auto reflectorData = toml::parse(stream, fileName.string());
54 validateTransformerConfig(reflectorData, "reflector", fileName.string());
55
56 ReflectorConfig reflectorConfig;
57 reflectorConfig.wiring = toml::find<std::array<AlphabetIndex, TRANSFORMER_SIZE>>(reflectorData, "reflector", "map");
58 return reflectorConfig;
59}
60
62 const AssetPath& assetPath) {
63 std::istringstream stream(provider.loadAsset(fileName.string()));
64 auto data = toml::parse(stream, fileName.string());
65
66 int rotorCount = toml::find<int>(data, "rotors", "RotorCount");
67 auto rotorPositions = toml::find<std::vector<AlphabetIndex>>(data, "rotors", "RotorPositions");
68 auto rotorFilePaths = toml::find<std::vector<std::string>>(data, "rotors", "RotorFiles");
69
70 if (static_cast<size_t>(rotorCount) != rotorPositions.size() ||
71 static_cast<size_t>(rotorCount) != rotorFilePaths.size()) {
72 throw std::runtime_error("Error: Number of rotors, positions, and files do not match.");
73 }
74
75 std::vector<RotorConfig> rotors;
76 rotors.reserve(rotorFilePaths.size());
77 std::ranges::transform(rotorFilePaths, std::back_inserter(rotors),
78 [&](const auto& rotorFile) { return loadRotor(provider, FileName(assetPath / rotorFile)); });
79
80 auto reflectorFile = toml::find<std::string>(data, "ReflectorFile");
81 auto reflector = loadReflector(provider, FileName(assetPath / reflectorFile));
82 auto plugsCount = toml::find<int>(data, "plugboard", "PlugCount");
83 if (plugsCount > PLUGBOARD_MAX_PAIRS) {
84 throw std::runtime_error("Error: Plugboard pairs exceed maximum allowed.");
85 }
86
87 auto plugBoardArr = toml::find<std::vector<toml::value>>(data, "plugboard", "PlugBoardPairs");
88 if (plugBoardArr.size() != static_cast<size_t>(plugsCount)) {
89 throw std::runtime_error("Error: Plugboard pairs count does not match specified count.");
90 }
91
92 std::array<PlugBoardPair, PLUGBOARD_MAX_PAIRS> plugBoardPairs;
93
94 for (int i = 0; i < plugsCount; i++) {
95 plugBoardPairs.at(i).sourcePortIndex = toml::find<int>(plugBoardArr.at(i), "from");
96 plugBoardPairs.at(i).destinationPortIndex = toml::find<int>(plugBoardArr.at(i), "to");
97 }
98
99 EnigmaMachineConfig newConfig;
100 newConfig.rotorCount = rotorCount;
101 newConfig.rotorPositions = std::move(rotorPositions);
102 newConfig.rotors = std::move(rotors);
103 newConfig.reflector = reflector;
104 newConfig.plugBoardPairs = plugBoardPairs;
105
106 return newConfig;
107}
static ReflectorConfig loadReflector(const IAssetProvider &provider, const FileName &fileName)
Loads a single reflector configuration from a TOML file.
static EnigmaMachineConfig load(const IAssetProvider &provider, const FileName &fileName, const AssetPath &assetPath=AssetPath())
Loads the complete Enigma Machine configuration from a TOML file.
static RotorConfig loadRotor(const IAssetProvider &provider, const FileName &fileName)
Loads a single rotor configuration from a TOML file.
Interface for providing configuration/asset data. Abstracts the source of assets (filesystem,...
virtual std::string loadAsset(std::string_view assetName) const =0
Loads the content of an asset.
Global configuration constants for the Enigma machine.
constexpr int TRANSFORMER_SIZE
Size of the alphabet/transformer (Standard Enigma is 26).
Definition config.hpp:10
constexpr int PLUGBOARD_MAX_PAIRS
Maximum number of allowed pairs on the plugboard.
Definition config.hpp:13
Strongly typed wrapper for asset paths. Used to distinguish between general file names and base asset...
Strongly typed wrapper for file names. Used to distinguish between general file names and base asset ...
Configuration Data Transfer Object (DTO) for the Enigma Machine. Holds the raw configuration data req...
std::vector< RotorConfig > rotors
Configuration for each rotor (in order).
std::vector< AlphabetIndex > rotorPositions
Initial rotational positions of the rotors.
std::array< PlugBoardPair, PLUGBOARD_MAX_PAIRS > plugBoardPairs
Plugboard connection pairs.
ReflectorConfig reflector
Configuration for the reflector.
int rotorCount
Number of rotors in the machine.
Configuration structure for a Reflector.
std::array< AlphabetIndex, TRANSFORMER_SIZE > wiring
The internal wiring permutation array (reflection map). Must be of size TRANSFORMER_SIZE.
Configuration structure for an individual Rotor.
AlphabetIndex notchPosition
The position (0 - (TRANSFORMER_SIZE - 1)) at which the rotor triggers the turnover of the next rotor.
std::array< AlphabetIndex, TRANSFORMER_SIZE > wiring
The internal wiring permutation array (forward direction). Must be of size TRANSFORMER_SIZE.