Dałeś taga C++ a nie C a ten kod wygląda jak kiepskie C.
Nie podoba się projekt tego API. Lepiej, gdy argumenty wejściowe nie są modyfikowane.
Kilka lepszych wersji API
Kopiuj
std::vector<char> crypt(const std::vector<char>& in, const std::vector<char>& key);
std::string crypt(const std::string& in, const std::string& key);
std::string crypt(std::string_view in, std::string_view key);
void crypt(const std::vector<char>& in, const std::vector<char>& key, std::vector<char>* out);
void crypt(std::string_view in, std::string_view key, std::string* out);
Co do samej implementacji:
Kopiuj
void crypt(std::string_view in, std::string_view key, std::string* out) {
out->clear();
out->resize(in.size());
auto key_it = key.begin();
for (auto [a, r] : std::views::zip(in, *out)) {
r = (a ^ *key_it) + 8;
++key_it;
if (key_it == key.end()) {
key_it = key.begin();
}
}
}
Niestety w C++ ranges nie ma widoku cycle (jest w bibliotece ranges v3, która była wzorem do ranges ze standardu C++)
Demo.
Swoją drogą wymyślanie swoich prymitywów kryptograficznych nie jest najlepszym pomysłem.
Lepiej nauczyć się używać gotowych rozwiązań z OpenSSL lub innej biblioteki.
Pytanie po co ci to jest potrzebne?
Mały poprawka:
Kopiuj
template <typename R>
concept RangeSafeForCycle = std::ranges::forward_range<R> && std::copyable<R>;
template <RangeSafeForCycle R>
auto make_inf_cycle(R r) -> std::generator<std::ranges::range_value_t<R>> {
auto it = std::ranges::begin(r);
const auto end = std::ranges::end(r);
while (true) {
co_yield *it;
if (++it == end) {
it = std::ranges::begin(r);
}
}
}
void crypt(std::string_view in, std::string_view key, std::string* out) {
out->clear();
out->resize(in.size());
for (auto [r, a, k] : std::views::zip(*out, in, make_inf_cycle(key))) {
r = (a ^ k) + 8;
}
}
https://godbolt.org/z/Y5MfeT3s1